pyntcli 0.1.84__py3-none-any.whl → 0.1.86__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 +11 -4
- pyntcli/commands/command.py +9 -4
- pyntcli/commands/har.py +13 -4
- pyntcli/commands/listen.py +11 -6
- pyntcli/commands/newman.py +12 -4
- pyntcli/commands/postman.py +5 -1
- pyntcli/commands/root.py +8 -1
- pyntcli/commands/util.py +2 -2
- pyntcli/main.py +18 -9
- pyntcli/pynt_docker/pynt_container.py +8 -1
- pyntcli/ui/pynt_errors.py +17 -5
- pyntcli/ui/ui_thread.py +50 -32
- {pyntcli-0.1.84.dist-info → pyntcli-0.1.86.dist-info}/METADATA +2 -2
- {pyntcli-0.1.84.dist-info → pyntcli-0.1.86.dist-info}/RECORD +18 -18
- {pyntcli-0.1.84.dist-info → pyntcli-0.1.86.dist-info}/WHEEL +0 -0
- {pyntcli-0.1.84.dist-info → pyntcli-0.1.86.dist-info}/entry_points.txt +0 -0
- {pyntcli-0.1.84.dist-info → pyntcli-0.1.86.dist-info}/top_level.txt +0 -0
pyntcli/__init__.py
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
__version__ = "0.1.
|
|
1
|
+
__version__ = "0.1.86"
|
pyntcli/commands/burp.py
CHANGED
|
@@ -261,6 +261,7 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
261
261
|
)
|
|
262
262
|
return
|
|
263
263
|
|
|
264
|
+
ui_thread.print_verbose("Parsing burp xml")
|
|
264
265
|
doc = parse_xml(args.xml)
|
|
265
266
|
if not doc:
|
|
266
267
|
ui_thread.print(
|
|
@@ -290,6 +291,12 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
290
291
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
291
292
|
|
|
292
293
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
294
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
295
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
296
|
+
"Pynt docker is ready",
|
|
297
|
+
ui_thread.PrinterText.INFO,
|
|
298
|
+
))
|
|
299
|
+
|
|
293
300
|
self._start_proxy(args)
|
|
294
301
|
|
|
295
302
|
run_burp_xml(doc, args.proxy_port)
|
|
@@ -304,10 +311,10 @@ class BurpCommand(sub_command.PyntSubCommand):
|
|
|
304
311
|
)
|
|
305
312
|
|
|
306
313
|
with ui_thread.progress(
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
314
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
315
|
+
partial(lambda *args: None),
|
|
316
|
+
"scan in progress...",
|
|
317
|
+
100,
|
|
311
318
|
):
|
|
312
319
|
html_report = self._get_report(args, "html")
|
|
313
320
|
html_report_path = os.path.join(
|
pyntcli/commands/command.py
CHANGED
|
@@ -161,6 +161,11 @@ class CommandSubCommand(sub_command.PyntSubCommand):
|
|
|
161
161
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
162
162
|
|
|
163
163
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
164
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
165
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
166
|
+
"Pynt docker is ready",
|
|
167
|
+
ui_thread.PrinterText.INFO,
|
|
168
|
+
))
|
|
164
169
|
|
|
165
170
|
if args.captured_domains:
|
|
166
171
|
ui_thread.print(
|
|
@@ -195,10 +200,10 @@ class CommandSubCommand(sub_command.PyntSubCommand):
|
|
|
195
200
|
self._stop_proxy(args)
|
|
196
201
|
|
|
197
202
|
with ui_thread.progress(
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
203
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
204
|
+
partial(lambda *args: None),
|
|
205
|
+
"scan in progress...",
|
|
206
|
+
100,
|
|
202
207
|
):
|
|
203
208
|
html_report = self._get_report(args, "html")
|
|
204
209
|
html_report_path = os.path.join(
|
pyntcli/commands/har.py
CHANGED
|
@@ -51,6 +51,7 @@ class HarSubCommand(sub_command.PyntSubCommand):
|
|
|
51
51
|
return har_cmd
|
|
52
52
|
|
|
53
53
|
def run_cmd(self, args: argparse.Namespace):
|
|
54
|
+
ui_thread.print_verbose("Building container")
|
|
54
55
|
port = util.find_open_port()
|
|
55
56
|
container = pynt_container.get_container_with_arguments(
|
|
56
57
|
args, pynt_container.PyntDockerPort(src=str(port), dest=port, name="--port")
|
|
@@ -92,13 +93,21 @@ class HarSubCommand(sub_command.PyntSubCommand):
|
|
|
92
93
|
healthcheck = partial(
|
|
93
94
|
util.wait_for_healthcheck, "http://localhost:{}".format(port)
|
|
94
95
|
)
|
|
96
|
+
|
|
97
|
+
healthcheck()
|
|
98
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
99
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
100
|
+
"Pynt docker is ready",
|
|
101
|
+
ui_thread.PrinterText.INFO,
|
|
102
|
+
))
|
|
103
|
+
|
|
95
104
|
ui_thread.print_generator(ui_thread.AnsiText.wrap_gen(har_docker.stdout))
|
|
96
105
|
|
|
97
106
|
with ui_thread.progress(
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
107
|
+
"ws://localhost:{}/progress".format(port),
|
|
108
|
+
healthcheck,
|
|
109
|
+
"scan in progress...",
|
|
110
|
+
100,
|
|
102
111
|
):
|
|
103
112
|
while har_docker.is_alive():
|
|
104
113
|
time.sleep(1)
|
pyntcli/commands/listen.py
CHANGED
|
@@ -57,7 +57,7 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
57
57
|
listen_cmd.add_argument("--allow-errors", action="store_true")
|
|
58
58
|
listen_cmd.add_argument("--ca-path", type=str, default="")
|
|
59
59
|
listen_cmd.add_argument("--report", type=str, default="")
|
|
60
|
-
listen_cmd.add_argument("--return-error", choices=["all-findings", "errors-only", "never"], default="never"
|
|
60
|
+
listen_cmd.add_argument("--return-error", choices=["all-findings", "errors-only", "never"], default="never")
|
|
61
61
|
listen_cmd.print_usage = self.print_usage
|
|
62
62
|
listen_cmd.print_help = self.print_usage
|
|
63
63
|
return listen_cmd
|
|
@@ -140,6 +140,11 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
140
140
|
ui_thread.print_generator(proxy_docker.stdout)
|
|
141
141
|
|
|
142
142
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
143
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
144
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
145
|
+
"Pynt docker is ready",
|
|
146
|
+
ui_thread.PrinterText.INFO,
|
|
147
|
+
))
|
|
143
148
|
|
|
144
149
|
self._start_proxy(args)
|
|
145
150
|
|
|
@@ -166,9 +171,9 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
166
171
|
self._stop_proxy(args)
|
|
167
172
|
|
|
168
173
|
with ui_thread.progress(
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
174
|
+
"ws://localhost:{}/progress?scanId={}".format(args.port, self.scan_id),
|
|
175
|
+
partial(lambda *args: None),
|
|
176
|
+
"scan in progress...", 100):
|
|
172
177
|
html_report = self._get_report(args, "html")
|
|
173
178
|
html_report_path = os.path.join(
|
|
174
179
|
tempfile.gettempdir(), "pynt_report_{}.html".format(int(time.time()))
|
|
@@ -185,12 +190,12 @@ class ListenSubCommand(sub_command.PyntSubCommand):
|
|
|
185
190
|
json_report_path = util.get_user_report_path(full_path, "json")
|
|
186
191
|
|
|
187
192
|
if html_report:
|
|
188
|
-
with open(html_report_path, "w",encoding="utf-8") as html_file:
|
|
193
|
+
with open(html_report_path, "w", encoding="utf-8") as html_file:
|
|
189
194
|
html_file.write(html_report)
|
|
190
195
|
webbrowser.open("file://{}".format(html_report_path))
|
|
191
196
|
|
|
192
197
|
if json_report:
|
|
193
|
-
with open(json_report_path, "w",encoding="utf-8") as json_file:
|
|
198
|
+
with open(json_report_path, "w", encoding="utf-8") as json_file:
|
|
194
199
|
json_file.write(json_report)
|
|
195
200
|
reporter = cli_reporter.PyntReporter(json_report_path)
|
|
196
201
|
reporter.print_summary()
|
pyntcli/commands/newman.py
CHANGED
|
@@ -114,13 +114,21 @@ class NewmanSubCommand(sub_command.PyntSubCommand):
|
|
|
114
114
|
healthcheck = partial(
|
|
115
115
|
util.wait_for_healthcheck, "http://localhost:{}".format(port)
|
|
116
116
|
)
|
|
117
|
+
|
|
118
|
+
healthcheck()
|
|
119
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
120
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
121
|
+
"Pynt docker is ready",
|
|
122
|
+
ui_thread.PrinterText.INFO,
|
|
123
|
+
))
|
|
124
|
+
|
|
117
125
|
ui_thread.print_generator(ui_thread.AnsiText.wrap_gen(newman_docker.stdout))
|
|
118
126
|
|
|
119
127
|
with ui_thread.progress(
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
128
|
+
"ws://localhost:{}/progress".format(port),
|
|
129
|
+
healthcheck,
|
|
130
|
+
"scan in progress...",
|
|
131
|
+
100,
|
|
124
132
|
):
|
|
125
133
|
while newman_docker.is_alive():
|
|
126
134
|
time.sleep(1)
|
pyntcli/commands/postman.py
CHANGED
|
@@ -94,7 +94,6 @@ class PostmanSubCommand(sub_command.PyntSubCommand):
|
|
|
94
94
|
|
|
95
95
|
container = pynt_container.get_container_with_arguments(args, pynt_container.PyntDockerPort("5001", args.port, name="--port"))
|
|
96
96
|
|
|
97
|
-
|
|
98
97
|
postman_docker = pynt_container.PyntContainer(image_name=pynt_container.PYNT_DOCKER_IMAGE,
|
|
99
98
|
tag="postman-latest",
|
|
100
99
|
detach=True,
|
|
@@ -104,6 +103,11 @@ class PostmanSubCommand(sub_command.PyntSubCommand):
|
|
|
104
103
|
ui_thread.print_generator(postman_docker.stdout)
|
|
105
104
|
|
|
106
105
|
util.wait_for_healthcheck("http://localhost:{}".format(args.port))
|
|
106
|
+
ui_thread.print_verbose(util.GOT_INITIAL_HEALTHCHECK_MESSAGE)
|
|
107
|
+
ui_thread.print(ui_thread.PrinterText(
|
|
108
|
+
"Pynt docker is ready",
|
|
109
|
+
ui_thread.PrinterText.INFO,
|
|
110
|
+
))
|
|
107
111
|
|
|
108
112
|
for scan_id in self.scan_id_generator(args.port):
|
|
109
113
|
html_report = self.get_report(args.port, "html", scan_id)
|
pyntcli/commands/root.py
CHANGED
|
@@ -22,7 +22,7 @@ def root_usage():
|
|
|
22
22
|
.with_line("\tpynt-id - view your pynt-id to use when running pynt in CI pipeline")
|
|
23
23
|
.with_line("\tlogout - log out from your user")
|
|
24
24
|
.with_line("")
|
|
25
|
-
.with_line("Run pynt [COMMAND] -h to get help on a specific command", style=ui_thread.PrinterText.INFO,)
|
|
25
|
+
.with_line("Run pynt [COMMAND] -h to get help on a specific command", style=ui_thread.PrinterText.INFO, )
|
|
26
26
|
)
|
|
27
27
|
|
|
28
28
|
|
|
@@ -68,6 +68,13 @@ class BaseCommand:
|
|
|
68
68
|
parser.add_argument("--transport-config", type=str, default="")
|
|
69
69
|
parser.add_argument("--application-id", type=str, default="", required=False)
|
|
70
70
|
parser.add_argument("--proxy", type=str, default="", required=False)
|
|
71
|
+
parser.add_argument(
|
|
72
|
+
"--verbose",
|
|
73
|
+
default=False,
|
|
74
|
+
required=False,
|
|
75
|
+
action="store_true",
|
|
76
|
+
help="use to get more detailed execution information",
|
|
77
|
+
)
|
|
71
78
|
|
|
72
79
|
def get_subparser(self) -> argparse._SubParsersAction:
|
|
73
80
|
if self.subparser is None:
|
pyntcli/commands/util.py
CHANGED
|
@@ -13,7 +13,6 @@ from pyntcli.pynt_docker import pynt_container
|
|
|
13
13
|
from pyntcli.ui import report
|
|
14
14
|
from pyntcli.transport import pynt_requests
|
|
15
15
|
|
|
16
|
-
|
|
17
16
|
logger = log.get_logger()
|
|
18
17
|
|
|
19
18
|
|
|
@@ -34,6 +33,7 @@ def find_open_port() -> int:
|
|
|
34
33
|
|
|
35
34
|
HEALTHCHECK_TIMEOUT = 60
|
|
36
35
|
HEALTHCHECK_INTERVAL = 0.1
|
|
36
|
+
GOT_INITIAL_HEALTHCHECK_MESSAGE = "Got initial pynt server health check"
|
|
37
37
|
|
|
38
38
|
|
|
39
39
|
def wait_for_healthcheck(address):
|
|
@@ -67,7 +67,7 @@ class SomeFindingsOrWarningsException(Exception):
|
|
|
67
67
|
pass
|
|
68
68
|
|
|
69
69
|
|
|
70
|
-
@
|
|
70
|
+
@contextmanager
|
|
71
71
|
def create_default_file_mounts(args):
|
|
72
72
|
html_report_path = os.path.join(tempfile.gettempdir(), "results.html")
|
|
73
73
|
json_report_path = os.path.join(tempfile.gettempdir(), "results.json")
|
pyntcli/main.py
CHANGED
|
@@ -33,18 +33,17 @@ def signal_handler(signal_number, frame):
|
|
|
33
33
|
exit(0)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
def
|
|
36
|
+
def assert_docker_availability():
|
|
37
37
|
pynt_container.get_docker_type()
|
|
38
38
|
|
|
39
39
|
|
|
40
40
|
def print_header():
|
|
41
41
|
ui_thread.print(ui_thread.PrinterText(*ui_thread.pynt_header())
|
|
42
|
-
|
|
43
|
-
|
|
42
|
+
.with_line(*ui_thread.pynt_version())
|
|
43
|
+
.with_line(""))
|
|
44
44
|
|
|
45
45
|
|
|
46
|
-
def start_analytics():
|
|
47
|
-
user_id = login.user_id()
|
|
46
|
+
def start_analytics(user_id: str):
|
|
48
47
|
if user_id:
|
|
49
48
|
analytics.set_user_id(user_id)
|
|
50
49
|
log.add_user_details(user_id)
|
|
@@ -66,12 +65,20 @@ def logout():
|
|
|
66
65
|
def main():
|
|
67
66
|
print_header()
|
|
68
67
|
try:
|
|
68
|
+
if len(argv) == 1:
|
|
69
|
+
pynt_cmd.root.usage()
|
|
70
|
+
return
|
|
69
71
|
if argv[1] == "logout":
|
|
70
72
|
logout()
|
|
71
73
|
return
|
|
74
|
+
if [n for n in argv if "--verbose" in n]:
|
|
75
|
+
ui_thread.VERBOSE = True
|
|
72
76
|
log.set_source(__version__)
|
|
73
|
-
|
|
74
|
-
|
|
77
|
+
ui_thread.print_verbose("Logging in...")
|
|
78
|
+
user_id = login.user_id()
|
|
79
|
+
start_analytics(user_id)
|
|
80
|
+
ui_thread.print_verbose("Asserting docker is properly installed")
|
|
81
|
+
assert_docker_availability()
|
|
75
82
|
signal.signal(signal.SIGINT, signal_handler)
|
|
76
83
|
cli = pynt_cmd.PyntCommand()
|
|
77
84
|
cli.run_cmd(cli.parse_args(argv[1:]))
|
|
@@ -82,7 +89,8 @@ def main():
|
|
|
82
89
|
ui_thread.print(ui_thread.PrinterText("Docker was unavailable, please make sure docker is installed and running.", ui_thread.PrinterText.WARNING))
|
|
83
90
|
analytics.emit(analytics.ERROR, {"error": "docker unavailable. e: {}".format(e)})
|
|
84
91
|
except SSLError as e:
|
|
85
|
-
ui_thread.print(
|
|
92
|
+
ui_thread.print(
|
|
93
|
+
ui_thread.PrinterText("We encountered SSL issues and could not proceed, this may be the cause of a VPN or a Firewall in place. Run again with --insecure", ui_thread.PrinterText.WARNING))
|
|
86
94
|
analytics.emit(analytics.ERROR, {"error": "ssl error. e: {}".format(e)})
|
|
87
95
|
except login.Timeout as e:
|
|
88
96
|
ui_thread.print(ui_thread.PrinterText("Pynt CLI exited due to incomplete registration, please try again.", ui_thread.PrinterText.WARNING))
|
|
@@ -114,7 +122,8 @@ def main():
|
|
|
114
122
|
exit(1)
|
|
115
123
|
except Exception as e:
|
|
116
124
|
analytics.emit(analytics.ERROR, {"error": "{}".format(e)})
|
|
117
|
-
pynt_errors.unexpected_error()
|
|
125
|
+
pynt_errors.unexpected_error(e)
|
|
126
|
+
|
|
118
127
|
finally:
|
|
119
128
|
log.flush_logger()
|
|
120
129
|
shutdown_cli()
|
|
@@ -106,6 +106,9 @@ def get_container_with_arguments(args: argparse.Namespace, *port_args: PyntDocke
|
|
|
106
106
|
docker_arguments += ["--transport-config", tc_name]
|
|
107
107
|
mounts.append(create_mount(os.path.abspath(args.transport_config), "/etc/pynt/{}".format(tc_name)))
|
|
108
108
|
|
|
109
|
+
if "verbose" in args and args.verbose:
|
|
110
|
+
docker_arguments.append("--verbose")
|
|
111
|
+
|
|
109
112
|
env = {PYNT_ID: CredStore().get_tokens(), "PYNT_SAAS_URL": PYNT_SAAS}
|
|
110
113
|
if user_set_all_variables():
|
|
111
114
|
add_env_variables(env)
|
|
@@ -184,7 +187,8 @@ class PyntContainer():
|
|
|
184
187
|
return self.docker_client.images.pull(self.image, tag=self.tag)
|
|
185
188
|
except APIError as e:
|
|
186
189
|
analytics.emit(analytics.ERROR, {"error": "Unable to pull image from ghcr: {}".format(e)})
|
|
187
|
-
ui_thread.print(ui_thread.PrinterText("Error: Docker unable to pull latest Pynt image due to VPN/proxy. If using a mirror for Docker images, visit docs.pynt.io for help.",
|
|
190
|
+
ui_thread.print(ui_thread.PrinterText("Error: Docker unable to pull latest Pynt image due to VPN/proxy. If using a mirror for Docker images, visit docs.pynt.io for help.",
|
|
191
|
+
ui_thread.PrinterText.WARNING))
|
|
188
192
|
return None
|
|
189
193
|
|
|
190
194
|
def get_image(self):
|
|
@@ -202,6 +206,8 @@ class PyntContainer():
|
|
|
202
206
|
self._create_docker_client()
|
|
203
207
|
|
|
204
208
|
self.running = True
|
|
209
|
+
|
|
210
|
+
ui_thread.print_verbose("Killing other pynt containers if such exist")
|
|
205
211
|
self.kill_other_instances()
|
|
206
212
|
|
|
207
213
|
ui_thread.print(ui_thread.PrinterText("Pulling latest docker", ui_thread.PrinterText.INFO))
|
|
@@ -222,6 +228,7 @@ class PyntContainer():
|
|
|
222
228
|
|
|
223
229
|
run_arguments.update(self.base_container.docker_type.get_argumets())
|
|
224
230
|
|
|
231
|
+
ui_thread.print_verbose("Running pynt docker with arguments:\n {}".format(" ".join(args)))
|
|
225
232
|
c = self.docker_client.containers.run(**run_arguments)
|
|
226
233
|
self.container_name = c.name
|
|
227
234
|
self.stdout = c.logs(stream=True)
|
pyntcli/ui/pynt_errors.py
CHANGED
|
@@ -1,7 +1,19 @@
|
|
|
1
1
|
from pyntcli.ui import ui_thread
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
|
|
4
|
+
def unexpected_error(original):
|
|
5
|
+
printer_text = ui_thread.PrinterText("An Unexpected Error Occurred", style=ui_thread.PrinterText.WARNING) \
|
|
6
|
+
.with_line("")
|
|
7
|
+
|
|
8
|
+
if ui_thread.VERBOSE:
|
|
9
|
+
msg = str(original) or repr(original)
|
|
10
|
+
if msg:
|
|
11
|
+
printer_text.with_line(f"e: {msg}")
|
|
12
|
+
|
|
13
|
+
printer_text = printer_text.with_line(
|
|
14
|
+
"Please tell us about it in our community channel and we will help you figure it out:",
|
|
15
|
+
style=ui_thread.PrinterText.HEADER) \
|
|
16
|
+
.with_line("https://join.slack.com/t/pynt-community/shared_invite/zt-1mvacojz5-WNjbH4HN8iksmKpCLTxOiQ",
|
|
17
|
+
style=ui_thread.PrinterText.HEADER)
|
|
18
|
+
|
|
19
|
+
ui_thread.print(printer_text)
|
pyntcli/ui/ui_thread.py
CHANGED
|
@@ -12,13 +12,16 @@ from typing import Tuple
|
|
|
12
12
|
from pyntcli import __version__ as cli_version
|
|
13
13
|
from pyntcli.ui.progress import PyntProgress
|
|
14
14
|
|
|
15
|
+
VERBOSE = False
|
|
16
|
+
|
|
17
|
+
|
|
15
18
|
class PrinterText():
|
|
16
19
|
DEFAULT = 0
|
|
17
20
|
HEADER = 1
|
|
18
21
|
INFO = 2
|
|
19
22
|
WARNING = 3
|
|
20
23
|
|
|
21
|
-
def __init__(self,text,style=DEFAULT):
|
|
24
|
+
def __init__(self, text, style=DEFAULT):
|
|
22
25
|
self.text = Text(text, PrinterText.get_style(style))
|
|
23
26
|
|
|
24
27
|
@staticmethod
|
|
@@ -37,57 +40,67 @@ class PrinterText():
|
|
|
37
40
|
self.text.append(Text(line, PrinterText.get_style(style)))
|
|
38
41
|
return self
|
|
39
42
|
|
|
43
|
+
|
|
40
44
|
class AnsiText():
|
|
41
45
|
def __init__(self, data) -> None:
|
|
42
46
|
self.data = data
|
|
43
|
-
|
|
47
|
+
|
|
44
48
|
@staticmethod
|
|
45
49
|
def wrap_gen(gen):
|
|
46
50
|
for v in gen:
|
|
47
51
|
yield AnsiText(v)
|
|
48
52
|
|
|
53
|
+
|
|
49
54
|
class Spinner():
|
|
50
55
|
def __init__(self, prompt, style) -> None:
|
|
51
56
|
self.prompt = prompt
|
|
52
|
-
self.style = style
|
|
57
|
+
self.style = style
|
|
53
58
|
self.runnning = False
|
|
54
|
-
|
|
59
|
+
|
|
55
60
|
def __enter__(self):
|
|
56
|
-
return self
|
|
61
|
+
return self
|
|
57
62
|
|
|
58
63
|
def __exit__(self, exc_type, exc_value, exc_traceback):
|
|
59
64
|
self.running = False
|
|
60
65
|
|
|
61
|
-
def pynt_version()-> Tuple[str,int]:
|
|
62
|
-
return "Pynt CLI version " + cli_version,PrinterText.DEFAULT
|
|
63
66
|
|
|
64
|
-
def
|
|
65
|
-
return "
|
|
67
|
+
def pynt_version() -> Tuple[str, int]:
|
|
68
|
+
return "Pynt CLI version " + cli_version, PrinterText.DEFAULT
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
def pynt_header() -> Tuple[str, int]:
|
|
72
|
+
return "API Security testing autopilot", PrinterText.DEFAULT
|
|
73
|
+
|
|
66
74
|
|
|
67
75
|
def gen_func_loop(gen):
|
|
68
76
|
for l in gen:
|
|
69
77
|
data = l
|
|
70
|
-
if type(data) == bytes:
|
|
78
|
+
if type(data) == bytes:
|
|
71
79
|
data = l.decode("utf-8")
|
|
72
80
|
if not isinstance(data, AnsiText) and data[-1] == "\n":
|
|
73
81
|
data = data[:-1]
|
|
74
82
|
_print(data)
|
|
75
|
-
|
|
83
|
+
|
|
84
|
+
|
|
76
85
|
def print_generator(gen):
|
|
77
|
-
t = Thread(target=gen_func_loop, args=(gen,), daemon=True)
|
|
86
|
+
t = Thread(target=gen_func_loop, args=(gen,), daemon=True)
|
|
78
87
|
t.start()
|
|
79
88
|
|
|
80
|
-
|
|
89
|
+
|
|
90
|
+
def _print(s):
|
|
81
91
|
Printer.instance().print(s)
|
|
82
92
|
|
|
83
|
-
|
|
84
|
-
|
|
93
|
+
|
|
94
|
+
def print(s):
|
|
95
|
+
if type(s) == bytes:
|
|
85
96
|
s = s.decode("utf-8")
|
|
86
97
|
_print(s)
|
|
87
98
|
|
|
99
|
+
|
|
88
100
|
def stop():
|
|
89
101
|
Printer.instance().stop()
|
|
90
102
|
|
|
103
|
+
|
|
91
104
|
class Printer():
|
|
92
105
|
_instace = None
|
|
93
106
|
|
|
@@ -96,31 +109,31 @@ class Printer():
|
|
|
96
109
|
self.run_thread = Thread(target=self._print_in_loop, daemon=True)
|
|
97
110
|
self.print_queue = queue.Queue()
|
|
98
111
|
self.console = Console(tab_size=4)
|
|
99
|
-
|
|
100
|
-
@staticmethod
|
|
112
|
+
|
|
113
|
+
@staticmethod
|
|
101
114
|
def instance():
|
|
102
115
|
if not Printer._instace:
|
|
103
|
-
Printer._instace = Printer()
|
|
104
|
-
Printer._instace.start()
|
|
116
|
+
Printer._instace = Printer()
|
|
117
|
+
Printer._instace.start()
|
|
105
118
|
|
|
106
119
|
return Printer._instace
|
|
107
120
|
|
|
108
121
|
def start(self):
|
|
109
122
|
self.running = True
|
|
110
123
|
self.run_thread.start()
|
|
111
|
-
|
|
124
|
+
|
|
112
125
|
def _handle_spinner(self, spinner):
|
|
113
|
-
spinner.running = True
|
|
126
|
+
spinner.running = True
|
|
114
127
|
s = Status(spinner.prompt, spinner=spinner.style, console=self.console)
|
|
115
128
|
s.start()
|
|
116
129
|
while spinner.running and self.running:
|
|
117
130
|
time.sleep(0.5)
|
|
118
131
|
s.stop()
|
|
119
|
-
|
|
132
|
+
|
|
120
133
|
def _handle_progress(self, progress):
|
|
121
134
|
if not progress.trackable:
|
|
122
135
|
return
|
|
123
|
-
progress.running = True
|
|
136
|
+
progress.running = True
|
|
124
137
|
with Progress(console=self.console, transient=True) as p:
|
|
125
138
|
t = p.add_task(description=progress.description, total=progress.total)
|
|
126
139
|
for update in progress.trackable:
|
|
@@ -131,9 +144,9 @@ class Printer():
|
|
|
131
144
|
|
|
132
145
|
def _print_in_loop(self):
|
|
133
146
|
while self.running:
|
|
134
|
-
try:
|
|
147
|
+
try:
|
|
135
148
|
data = self.print_queue.get(timeout=1)
|
|
136
|
-
if isinstance(data, list):
|
|
149
|
+
if isinstance(data, list):
|
|
137
150
|
data = data[0]
|
|
138
151
|
if isinstance(data, Spinner):
|
|
139
152
|
self._handle_spinner(data)
|
|
@@ -148,29 +161,34 @@ class Printer():
|
|
|
148
161
|
self.console.print(data)
|
|
149
162
|
except queue.Empty:
|
|
150
163
|
pass
|
|
151
|
-
|
|
164
|
+
|
|
152
165
|
while not self.print_queue.empty():
|
|
153
166
|
self.console.print(self.print_queue.get())
|
|
154
167
|
|
|
155
|
-
|
|
156
168
|
def print(self, data):
|
|
157
|
-
if isinstance(data,PrinterText):
|
|
169
|
+
if isinstance(data, PrinterText):
|
|
158
170
|
data = data.text
|
|
159
171
|
if isinstance(data, AnsiText):
|
|
160
172
|
data = Text.from_ansi(data.data.decode())
|
|
161
173
|
self.print_queue.put(data)
|
|
162
|
-
|
|
174
|
+
|
|
163
175
|
def stop(self):
|
|
164
176
|
self.running = False
|
|
165
177
|
self.run_thread.join()
|
|
166
178
|
|
|
167
|
-
|
|
179
|
+
|
|
180
|
+
def spinner(prompt, style):
|
|
168
181
|
s = Spinner(prompt, style)
|
|
169
182
|
_print([s])
|
|
170
183
|
return s
|
|
171
184
|
|
|
172
|
-
|
|
173
|
-
|
|
185
|
+
|
|
186
|
+
def progress(what_to_track, healthcheck, description, total=100):
|
|
187
|
+
pointer_to_progress = [PyntProgress(what_to_track, healthcheck, total, description)]
|
|
174
188
|
_print(pointer_to_progress)
|
|
175
189
|
return pointer_to_progress[0]
|
|
176
190
|
|
|
191
|
+
|
|
192
|
+
def print_verbose(text: str):
|
|
193
|
+
if VERBOSE:
|
|
194
|
+
print(PrinterText(text, PrinterText.INFO))
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: pyntcli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.86
|
|
4
4
|
Summary: Command line utility to handle all of Pynt's different integrations
|
|
5
5
|
Author-email: Pynt-io <support@pynt.io>
|
|
6
6
|
Project-URL: Homepage, https://pynt.io
|
|
7
7
|
Requires-Python: >=3.7
|
|
8
8
|
Requires-Dist: docker
|
|
9
9
|
Requires-Dist: rich
|
|
10
|
-
Requires-Dist: requests
|
|
10
|
+
Requires-Dist: requests ==2.31.0
|
|
11
11
|
Requires-Dist: pem
|
|
12
12
|
Requires-Dist: certifi >=2017.4.17
|
|
13
13
|
Requires-Dist: logzio-python-handler >=4.1.0
|
|
@@ -1,27 +1,27 @@
|
|
|
1
|
-
pyntcli/__init__.py,sha256=
|
|
2
|
-
pyntcli/main.py,sha256=
|
|
1
|
+
pyntcli/__init__.py,sha256=daW0dTSMLeXJ53ouWqpbphS98YVWhR0zyXXnZpqK-Ps,23
|
|
2
|
+
pyntcli/main.py,sha256=eJFpT-haLVQAYP71_ZHjNaA5iG2wvDXy8km84GU0Mwo,6009
|
|
3
3
|
pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
pyntcli/analytics/send.py,sha256=pJOyOWl3g_Vm9apKK3LzNVqsnC6zsWA1bCK3ZegbLpc,3637
|
|
5
5
|
pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
6
|
pyntcli/auth/login.py,sha256=TljsRXbEkNI1YUrKm5mlTw4YiecYScYUsit8Z8vstss,5228
|
|
7
7
|
pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
pyntcli/commands/burp.py,sha256=
|
|
9
|
-
pyntcli/commands/command.py,sha256=
|
|
10
|
-
pyntcli/commands/har.py,sha256
|
|
8
|
+
pyntcli/commands/burp.py,sha256=tDGWzgHKfMnKot1jI7JghvHk29VMZsnfcyNuRZTO2Lk,11753
|
|
9
|
+
pyntcli/commands/command.py,sha256=076tUOnqHBSogoGt8h2fnyZWeGWO5eEfHIECbefdS1s,9715
|
|
10
|
+
pyntcli/commands/har.py,sha256=-RxuX_lw7JAY46oxHlp5N9Twm5Sc3VLVbHpWEwtuGFg,3976
|
|
11
11
|
pyntcli/commands/id_command.py,sha256=UBEgMIpm4vauTCsKyixltiGUolNg_OfHEJvJ_i5BpJY,943
|
|
12
|
-
pyntcli/commands/listen.py,sha256=
|
|
13
|
-
pyntcli/commands/newman.py,sha256=
|
|
14
|
-
pyntcli/commands/postman.py,sha256=
|
|
12
|
+
pyntcli/commands/listen.py,sha256=Mm5TY5e896-NhDOImRUB3N8gaaXtcZdCSdV92NLt8eM,8702
|
|
13
|
+
pyntcli/commands/newman.py,sha256=qvrVLL3BqiugdNPTi-KBI-BXXDYMSRMu4BPEs6Dfz_U,5094
|
|
14
|
+
pyntcli/commands/postman.py,sha256=CgX4KTF8qR008LiIsiSrNLyXdgPre3CwVz3AENnOcB8,4924
|
|
15
15
|
pyntcli/commands/pynt_cmd.py,sha256=KOl9guUtesO2JcMM5nPKKkjnK6F9HV4jHHcoUk4KVhw,2825
|
|
16
|
-
pyntcli/commands/root.py,sha256=
|
|
16
|
+
pyntcli/commands/root.py,sha256=inffMhaMJykoRC0T2f7uF3f5BEdJw_c6Q1e2FTG4bfU,3511
|
|
17
17
|
pyntcli/commands/static_file_extensions.py,sha256=PZJb02BI-64tbU-j3rdCNsXzTh7gkIDGxGKbKNw3h5k,1995
|
|
18
18
|
pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
|
|
19
|
-
pyntcli/commands/util.py,sha256=
|
|
19
|
+
pyntcli/commands/util.py,sha256=spTI_3z-fd0q7o1htvl-mw9-yKbO2ZESDAL-AsgWCb0,3217
|
|
20
20
|
pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
|
|
21
21
|
pyntcli/log/log.py,sha256=cWCdWmUaAwePwdhYDcgNMEG9d9RM34sGahxBCYEdv2Y,1069
|
|
22
22
|
pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
|
|
23
23
|
pyntcli/pynt_docker/container_utils.py,sha256=_Onn7loInzyJAG2-Uk6CGpsuRyelmUFHOvtJj4Uzi9A,175
|
|
24
|
-
pyntcli/pynt_docker/pynt_container.py,sha256=
|
|
24
|
+
pyntcli/pynt_docker/pynt_container.py,sha256=c3gwOpPvDRWofHqv1p-jsQ24TQOlBFdFqYbwFMiJ0Rs,9079
|
|
25
25
|
pyntcli/store/__init__.py,sha256=xuS9OB21F6B1sUx5XPGxz_6WpG6-KTMbuq50RrZS5OY,29
|
|
26
26
|
pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
|
|
27
27
|
pyntcli/store/store.py,sha256=9KwalOd1EA1VtYwr9oJgBsPgUYakX5uyif_sNXGQ614,1917
|
|
@@ -30,14 +30,14 @@ pyntcli/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU
|
|
|
30
30
|
pyntcli/transport/pynt_requests.py,sha256=KiEG3hNcwY7DLIJDCq-7LIPq54yYQcDBhHe3KhpqRTc,1563
|
|
31
31
|
pyntcli/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
32
32
|
pyntcli/ui/progress.py,sha256=RrnO_jJNunoyupylakmWmHOEPw3lh99OHpKBzL6OBiE,1008
|
|
33
|
-
pyntcli/ui/pynt_errors.py,sha256=
|
|
33
|
+
pyntcli/ui/pynt_errors.py,sha256=Pwxf2eIkXbQg060vnaMm4ivthbohDalxVDK6-Kag2iU,727
|
|
34
34
|
pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
|
|
35
|
-
pyntcli/ui/ui_thread.py,sha256=
|
|
35
|
+
pyntcli/ui/ui_thread.py,sha256=4YzpO5dDrWpbTovMdHvv9ZQdLFJamZEAKXjF9rIIIoQ,5039
|
|
36
36
|
tests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
|
|
37
37
|
tests/auth/test_login.py,sha256=KFlzWhXBAuwdi7GXf16gCB3ya94LQG2wjcSChE149rQ,3798
|
|
38
38
|
tests/store/test_cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
|
|
39
|
-
pyntcli-0.1.
|
|
40
|
-
pyntcli-0.1.
|
|
41
|
-
pyntcli-0.1.
|
|
42
|
-
pyntcli-0.1.
|
|
43
|
-
pyntcli-0.1.
|
|
39
|
+
pyntcli-0.1.86.dist-info/METADATA,sha256=7vQ3Epe9eMRgT06mRKDpiwrzSNi-qsa1lwubvzouPDM,463
|
|
40
|
+
pyntcli-0.1.86.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
41
|
+
pyntcli-0.1.86.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
|
|
42
|
+
pyntcli-0.1.86.dist-info/top_level.txt,sha256=u9MDStwVHB7UG8PUcODeWCul_NvzL2EzoLvSlgwLHFs,30
|
|
43
|
+
pyntcli-0.1.86.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|