pyntcli 0.1.73__py3-none-any.whl → 0.1.75__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/analytics/send.py +32 -17
- pyntcli/auth/login.py +41 -31
- pyntcli/commands/burp.py +8 -16
- pyntcli/commands/command.py +15 -30
- pyntcli/commands/har.py +2 -2
- pyntcli/commands/id_command.py +5 -3
- pyntcli/commands/listen.py +20 -45
- pyntcli/commands/newman.py +4 -4
- pyntcli/commands/postman.py +26 -28
- pyntcli/commands/pynt_cmd.py +27 -13
- pyntcli/commands/root.py +2 -0
- pyntcli/commands/util.py +26 -24
- pyntcli/log/log.py +2 -1
- pyntcli/main.py +30 -22
- pyntcli/pynt_docker/container_utils.py +7 -0
- pyntcli/pynt_docker/pynt_container.py +82 -58
- pyntcli/store/store.py +19 -14
- {pyntcli-0.1.73.dist-info → pyntcli-0.1.75.dist-info}/METADATA +1 -1
- pyntcli-0.1.75.dist-info/RECORD +42 -0
- tests/auth/test_login.py +17 -19
- pyntcli-0.1.73.dist-info/RECORD +0 -41
- {pyntcli-0.1.73.dist-info → pyntcli-0.1.75.dist-info}/WHEEL +0 -0
- {pyntcli-0.1.73.dist-info → pyntcli-0.1.75.dist-info}/entry_points.txt +0 -0
- {pyntcli-0.1.73.dist-info → pyntcli-0.1.75.dist-info}/top_level.txt +0 -0
|
@@ -6,22 +6,34 @@ import argparse
|
|
|
6
6
|
from typing import List
|
|
7
7
|
import base64
|
|
8
8
|
|
|
9
|
+
from . import container_utils
|
|
10
|
+
|
|
9
11
|
from pyntcli.ui import ui_thread
|
|
10
12
|
from pyntcli.analytics import send as analytics
|
|
11
13
|
from pyntcli.store import CredStore
|
|
12
|
-
from pyntcli.auth.login import
|
|
14
|
+
from pyntcli.auth.login import PYNT_ID, PYNT_SAAS, PYNT_BUCKET_NAME, PYNT_PARAM1, PYNT_PARAM2
|
|
13
15
|
|
|
14
16
|
PYNT_DOCKER_IMAGE = "ghcr.io/pynt-io/pynt"
|
|
15
17
|
|
|
18
|
+
|
|
16
19
|
def create_mount(src, destination, mount_type="bind"):
|
|
17
20
|
return Mount(target=destination, source=src, type=mount_type)
|
|
18
21
|
|
|
22
|
+
|
|
19
23
|
class DockerNotAvailableException(Exception):
|
|
20
24
|
pass
|
|
21
25
|
|
|
26
|
+
|
|
22
27
|
class ImageUnavailableException(Exception):
|
|
23
28
|
pass
|
|
24
29
|
|
|
30
|
+
|
|
31
|
+
class PortInUseException(Exception):
|
|
32
|
+
def __init__(self, port=""):
|
|
33
|
+
self.message = ui_thread.print(ui_thread.PrinterText("Port: {} already in use, please use a different one".format(port), ui_thread.PrinterText.WARNING))
|
|
34
|
+
super().__init__(self.message)
|
|
35
|
+
|
|
36
|
+
|
|
25
37
|
def get_docker_type():
|
|
26
38
|
try:
|
|
27
39
|
c = docker.from_env()
|
|
@@ -30,53 +42,59 @@ def get_docker_type():
|
|
|
30
42
|
analytics.deferred_emit(analytics.DOCKER_PLATFORM, platform)
|
|
31
43
|
if platform and platform.get("Name"):
|
|
32
44
|
return platform.get("Name")
|
|
33
|
-
|
|
45
|
+
|
|
34
46
|
return ""
|
|
35
47
|
|
|
36
48
|
except DockerException:
|
|
37
49
|
raise DockerNotAvailableException()
|
|
38
|
-
except Exception:
|
|
50
|
+
except Exception: # TODO: This is since windows is not behaving nice
|
|
39
51
|
raise DockerNotAvailableException()
|
|
40
52
|
|
|
41
53
|
|
|
42
54
|
class PyntBaseConatiner():
|
|
43
|
-
def __init__(self,docker_type,docker_arguments,mounts, environment={}) -> None:
|
|
55
|
+
def __init__(self, docker_type, docker_arguments, mounts, environment={}) -> None:
|
|
44
56
|
self.docker_type = docker_type
|
|
45
57
|
self.docker_arguments = docker_arguments
|
|
46
58
|
self.mounts = mounts
|
|
47
59
|
self.environment = environment
|
|
48
60
|
|
|
61
|
+
|
|
49
62
|
class PyntDockerPort:
|
|
50
63
|
def __init__(self, src, dest, name) -> None:
|
|
51
64
|
self.src = src
|
|
52
65
|
self.dest = dest
|
|
53
66
|
self.name = name
|
|
54
67
|
|
|
55
|
-
|
|
68
|
+
|
|
69
|
+
def get_container_with_arguments(args: argparse.Namespace, *port_args: PyntDockerPort) -> PyntBaseConatiner:
|
|
56
70
|
docker_arguments = []
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
ports = {}
|
|
72
|
+
for p in port_args:
|
|
73
|
+
if container_utils.is_port_in_use(p.dest):
|
|
74
|
+
raise PortInUseException(p.dest)
|
|
75
|
+
if "desktop" in get_docker_type().lower():
|
|
60
76
|
ports[str(p.src)] = int(p.dest)
|
|
77
|
+
else:
|
|
78
|
+
docker_arguments.append(p.name)
|
|
79
|
+
docker_arguments.append(str(p.dest))
|
|
80
|
+
|
|
81
|
+
if "desktop" in get_docker_type().lower():
|
|
61
82
|
docker_type = PyntDockerDesktopContainer(ports=ports)
|
|
62
83
|
else:
|
|
63
84
|
docker_type = PyntNativeContainer(network="host")
|
|
64
|
-
|
|
65
|
-
docker_arguments.append(p.name)
|
|
66
|
-
docker_arguments.append(str(p.dest))
|
|
67
|
-
|
|
85
|
+
|
|
68
86
|
if "insecure" in args and args.insecure:
|
|
69
87
|
docker_arguments.append("--insecure")
|
|
70
|
-
|
|
71
|
-
if "application_id" in args and args.application_id:
|
|
72
|
-
docker_arguments += ["--application-id",args.application_id]
|
|
73
88
|
|
|
74
|
-
if "
|
|
75
|
-
docker_arguments += ["--
|
|
89
|
+
if "application_id" in args and args.application_id:
|
|
90
|
+
docker_arguments += ["--application-id", args.application_id]
|
|
91
|
+
|
|
92
|
+
if "proxy" in args and args.proxy:
|
|
93
|
+
docker_arguments += ["--proxy", args.proxy]
|
|
76
94
|
|
|
77
|
-
if "dev_flags" in args:
|
|
95
|
+
if "dev_flags" in args:
|
|
78
96
|
docker_arguments += args.dev_flags.split(" ")
|
|
79
|
-
|
|
97
|
+
|
|
80
98
|
mounts = []
|
|
81
99
|
if "host_ca" in args and args.host_ca:
|
|
82
100
|
ca_name = os.path.basename(args.host_ca)
|
|
@@ -87,38 +105,41 @@ def get_container_with_arguments(args: argparse.Namespace , *port_args: PyntDock
|
|
|
87
105
|
tc_name = os.path.basename(args.transport_config)
|
|
88
106
|
docker_arguments += ["--transport-config", tc_name]
|
|
89
107
|
mounts.append(create_mount(os.path.abspath(args.transport_config), "/etc/pynt/{}".format(tc_name)))
|
|
90
|
-
|
|
91
|
-
env = {
|
|
108
|
+
|
|
109
|
+
env = {PYNT_ID: CredStore().get_tokens(), "PYNT_SAAS_URL": PYNT_SAAS}
|
|
92
110
|
if user_set_all_variables():
|
|
93
111
|
add_env_variables(env)
|
|
94
112
|
return PyntBaseConatiner(docker_type, docker_arguments, mounts, env)
|
|
95
|
-
|
|
113
|
+
|
|
114
|
+
|
|
96
115
|
def _container_image_from_tag(tag: str) -> str:
|
|
97
|
-
if ":" in tag:
|
|
116
|
+
if ":" in tag:
|
|
98
117
|
return tag.split(":")[0]
|
|
99
118
|
|
|
100
119
|
return tag
|
|
101
120
|
|
|
121
|
+
|
|
102
122
|
def user_set_all_variables():
|
|
103
|
-
|
|
104
|
-
|
|
123
|
+
return all([PYNT_BUCKET_NAME, PYNT_PARAM1, PYNT_PARAM2])
|
|
124
|
+
|
|
125
|
+
|
|
105
126
|
def add_env_variables(env: dict):
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
127
|
+
env["PYNT_BUCKET_NAME"] = PYNT_BUCKET_NAME
|
|
128
|
+
env["PYNT_PARAM1"] = base64.b64encode(PYNT_PARAM1.encode('utf-8'))
|
|
129
|
+
env["PYNT_PARAM2"] = base64.b64encode(PYNT_PARAM2.encode('utf-8'))
|
|
130
|
+
|
|
131
|
+
|
|
110
132
|
class PyntContainer():
|
|
111
133
|
def __init__(self, image_name, tag, detach, base_container: PyntBaseConatiner) -> None:
|
|
112
134
|
self.docker_client: docker.DockerClient = None
|
|
113
135
|
self.image = image_name if not os.environ.get("IMAGE") else os.environ.get("IMAGE")
|
|
114
136
|
self.tag = tag if not os.environ.get("TAG") else os.environ.get("TAG")
|
|
115
137
|
self.detach = detach
|
|
116
|
-
self.stdout = None
|
|
138
|
+
self.stdout = None
|
|
117
139
|
self.running = False
|
|
118
140
|
self.container_name = ""
|
|
119
141
|
self.base_container = base_container
|
|
120
142
|
|
|
121
|
-
|
|
122
143
|
def _create_docker_client(self):
|
|
123
144
|
self.docker_client = docker.from_env()
|
|
124
145
|
pat = os.environ.get("DOCKER_PASSWORD")
|
|
@@ -126,28 +147,28 @@ class PyntContainer():
|
|
|
126
147
|
registry = os.environ.get("DOCKER_REGISTRY")
|
|
127
148
|
if pat and username and registry:
|
|
128
149
|
self.docker_client.login(username=username, password=pat, registry=registry)
|
|
129
|
-
|
|
150
|
+
|
|
130
151
|
def _is_docker_image_up_to_date(self, image):
|
|
131
152
|
return True
|
|
132
|
-
|
|
153
|
+
|
|
133
154
|
def _handle_outdated_docker_image(self, image):
|
|
134
155
|
return image
|
|
135
|
-
|
|
156
|
+
|
|
136
157
|
def kill_other_instances(self):
|
|
137
158
|
for c in self.docker_client.containers.list():
|
|
138
159
|
if len(c.image.tags) and _container_image_from_tag(c.image.tags[0]) == self.image:
|
|
139
160
|
c.kill()
|
|
140
|
-
|
|
161
|
+
|
|
141
162
|
def stop(self):
|
|
142
163
|
if not self.running:
|
|
143
|
-
return
|
|
164
|
+
return
|
|
144
165
|
|
|
145
166
|
self.kill_other_instances()
|
|
146
167
|
|
|
147
168
|
self.docker_client.close()
|
|
148
169
|
self.docker_client = None
|
|
149
170
|
self.running = False
|
|
150
|
-
|
|
171
|
+
|
|
151
172
|
def is_alive(self):
|
|
152
173
|
if not self.docker_client or not self.container_name:
|
|
153
174
|
return False
|
|
@@ -155,47 +176,48 @@ class PyntContainer():
|
|
|
155
176
|
l = self.docker_client.containers.list(filters={"name": self.container_name})
|
|
156
177
|
if len(l) != 1:
|
|
157
178
|
return False
|
|
158
|
-
|
|
179
|
+
|
|
159
180
|
return l[0].status == "running"
|
|
160
|
-
|
|
181
|
+
|
|
161
182
|
def pull_image(self):
|
|
162
183
|
try:
|
|
163
184
|
return self.docker_client.images.pull(self.image, tag=self.tag)
|
|
164
185
|
except APIError as e:
|
|
165
|
-
analytics.emit(analytics.ERROR,{"error": "Unable to pull image from ghcr: {}".format(e)})
|
|
186
|
+
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.", ui_thread.PrinterText.WARNING))
|
|
166
188
|
return None
|
|
167
189
|
|
|
168
190
|
def get_image(self):
|
|
169
191
|
try:
|
|
170
192
|
image = self.pull_image()
|
|
171
193
|
if not image:
|
|
172
|
-
|
|
194
|
+
ui_thread.print(ui_thread.PrinterText("Trying to get pynt local image", ui_thread.PrinterText.INFO))
|
|
195
|
+
image = self.docker_client.images.get('{}:{}'.format(self.image, self.tag))
|
|
173
196
|
return image
|
|
174
197
|
except ImageNotFound:
|
|
175
198
|
raise ImageUnavailableException()
|
|
176
199
|
|
|
177
|
-
def run(self):
|
|
200
|
+
def run(self):
|
|
178
201
|
if not self.docker_client:
|
|
179
202
|
self._create_docker_client()
|
|
180
|
-
|
|
203
|
+
|
|
181
204
|
self.running = True
|
|
182
205
|
self.kill_other_instances()
|
|
183
206
|
|
|
184
207
|
ui_thread.print(ui_thread.PrinterText("Pulling latest docker", ui_thread.PrinterText.INFO))
|
|
185
208
|
image = self.get_image()
|
|
186
209
|
ui_thread.print(ui_thread.PrinterText("Docker pull done", ui_thread.PrinterText.INFO))
|
|
187
|
-
|
|
210
|
+
|
|
188
211
|
args = self.base_container.docker_arguments if self.base_container.docker_arguments else None
|
|
189
|
-
|
|
190
212
|
|
|
191
213
|
run_arguments = {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
214
|
+
"image": image,
|
|
215
|
+
"detach": self.detach,
|
|
216
|
+
"mounts": self.base_container.mounts,
|
|
217
|
+
"environment": self.base_container.environment,
|
|
218
|
+
"stream": True,
|
|
219
|
+
"remove": True,
|
|
220
|
+
"command": args
|
|
199
221
|
}
|
|
200
222
|
|
|
201
223
|
run_arguments.update(self.base_container.docker_type.get_argumets())
|
|
@@ -206,13 +228,15 @@ class PyntContainer():
|
|
|
206
228
|
|
|
207
229
|
PyntContainerRegistery.instance().register_container(self)
|
|
208
230
|
|
|
231
|
+
|
|
209
232
|
class PyntDockerDesktopContainer():
|
|
210
233
|
def __init__(self, ports) -> None:
|
|
211
234
|
self.ports = ports
|
|
212
|
-
|
|
235
|
+
|
|
213
236
|
def get_argumets(self):
|
|
214
237
|
return {"ports": self.ports} if self.ports else {}
|
|
215
|
-
|
|
238
|
+
|
|
239
|
+
|
|
216
240
|
class PyntNativeContainer():
|
|
217
241
|
def __init__(self, network) -> None:
|
|
218
242
|
self.network = network
|
|
@@ -230,13 +254,13 @@ class PyntContainerRegistery():
|
|
|
230
254
|
@staticmethod
|
|
231
255
|
def instance():
|
|
232
256
|
if not PyntContainerRegistery._instance:
|
|
233
|
-
PyntContainerRegistery._instance = PyntContainerRegistery()
|
|
257
|
+
PyntContainerRegistery._instance = PyntContainerRegistery()
|
|
234
258
|
|
|
235
259
|
return PyntContainerRegistery._instance
|
|
236
260
|
|
|
237
261
|
def register_container(self, c: PyntContainer):
|
|
238
|
-
self.containers.append(c)
|
|
239
|
-
|
|
262
|
+
self.containers.append(c)
|
|
263
|
+
|
|
240
264
|
def stop_all_containers(self):
|
|
241
|
-
for c in self.containers:
|
|
265
|
+
for c in self.containers:
|
|
242
266
|
c.stop()
|
pyntcli/store/store.py
CHANGED
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
from typing import Type
|
|
2
|
-
import os
|
|
3
|
-
import platform
|
|
1
|
+
from typing import Type
|
|
2
|
+
import os
|
|
4
3
|
|
|
5
4
|
from .json_connector import JsonStoreConnector
|
|
6
5
|
from .store_connector import StoreConnector
|
|
7
6
|
|
|
7
|
+
|
|
8
8
|
class Store():
|
|
9
|
-
def __init__(self, file_location: str, connector_type: Type[StoreConnector]) -> None
|
|
9
|
+
def __init__(self, file_location: str, connector_type: Type[StoreConnector]) -> None:
|
|
10
10
|
self.file_location = file_location
|
|
11
|
-
self.connector:StoreConnector = None
|
|
11
|
+
self.connector: StoreConnector = None
|
|
12
12
|
self._file = None
|
|
13
13
|
self._connector_tpye = connector_type
|
|
14
|
-
|
|
14
|
+
|
|
15
15
|
def _get_file_data(self):
|
|
16
|
-
if self.connector:
|
|
17
|
-
return
|
|
16
|
+
if self.connector:
|
|
17
|
+
return
|
|
18
18
|
|
|
19
19
|
dirname = os.path.dirname(self.file_location)
|
|
20
20
|
if not os.path.exists(dirname):
|
|
21
21
|
os.makedirs(dirname)
|
|
22
|
-
|
|
22
|
+
|
|
23
23
|
if not os.path.exists(self.file_location):
|
|
24
24
|
with open(self.file_location, "w") as f:
|
|
25
25
|
self.connector = self._connector_tpye(self._connector_tpye.default_value())
|
|
@@ -35,24 +35,29 @@ class Store():
|
|
|
35
35
|
def put(self, key, value):
|
|
36
36
|
self._get_file_data()
|
|
37
37
|
self.connector.put(key, value)
|
|
38
|
-
|
|
38
|
+
|
|
39
39
|
def get_path(self):
|
|
40
40
|
return self.file_location
|
|
41
41
|
|
|
42
42
|
def __enter__(self):
|
|
43
43
|
self._get_file_data()
|
|
44
|
-
return self
|
|
44
|
+
return self
|
|
45
45
|
|
|
46
|
-
def __exit__(self, type, value, traceback):
|
|
46
|
+
def __exit__(self, type, value, traceback):
|
|
47
47
|
with open(self.file_location, "w") as f:
|
|
48
48
|
f.write(self.connector.dump())
|
|
49
49
|
|
|
50
|
+
|
|
50
51
|
class CredStore(Store):
|
|
51
52
|
def __init__(self) -> None:
|
|
52
53
|
dir = ".pynt"
|
|
53
54
|
super().__init__(file_location=os.path.join(os.path.expanduser("~"), dir, "creds.json"),
|
|
54
55
|
connector_type=JsonStoreConnector)
|
|
55
|
-
|
|
56
|
+
|
|
56
57
|
def get_access_token(self):
|
|
57
58
|
return self.get("token")["access_token"]
|
|
58
|
-
|
|
59
|
+
|
|
60
|
+
def get_tokens(self):
|
|
61
|
+
all_tokens = self.get("token")
|
|
62
|
+
token_to_json_string = '{"token":'+str(all_tokens).replace("\'", "\"")+"}"
|
|
63
|
+
return token_to_json_string
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
pyntcli/__init__.py,sha256=FJWQjdyjCSq1G0xvL-leZBsVKT8Trwi_Y3BZDT0-Bus,23
|
|
2
|
+
pyntcli/main.py,sha256=7ZDeG3IO04T98D2NJ1vHWVAVJVm8y719NeV2Aom7tPY,5171
|
|
3
|
+
pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
pyntcli/analytics/send.py,sha256=cKvMw4HIGJGLip5OMPqTv1AJDlKlc_Uk2Sfcl0e3QLE,2845
|
|
5
|
+
pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
+
pyntcli/auth/login.py,sha256=CosHIB1HHWa3cGjpE4uHNxsi_7SPL-I6Da0zCq3OcmU,5012
|
|
7
|
+
pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
+
pyntcli/commands/burp.py,sha256=tbGpKP4NEuEZYSuBxqvLJaC4kRqtv0GO6BpBfPX2DRM,10397
|
|
9
|
+
pyntcli/commands/command.py,sha256=UvJEHv69iQ03R0pN2RCsi3my48xwSMoDBTvcnbg_XzE,9477
|
|
10
|
+
pyntcli/commands/har.py,sha256=mSCbTUnxQrKzJd-dAWoc6Tkw6tU1LDH7Ha1w2ylrrrg,3654
|
|
11
|
+
pyntcli/commands/id_command.py,sha256=UBEgMIpm4vauTCsKyixltiGUolNg_OfHEJvJ_i5BpJY,943
|
|
12
|
+
pyntcli/commands/listen.py,sha256=ZfzCM8P0TVweC42NCL24_1yK48_NvRER6Vi8_oChaT0,8450
|
|
13
|
+
pyntcli/commands/newman.py,sha256=y0KolwMgsvoqPz2mp0QRug_qNr-ftOZbu_tN7h4bH7I,4826
|
|
14
|
+
pyntcli/commands/postman.py,sha256=GWq4NJJ_9WdFiXk5rv2nTyMM27w50XLh4LKkuuWpw4I,4721
|
|
15
|
+
pyntcli/commands/pynt_cmd.py,sha256=KOl9guUtesO2JcMM5nPKKkjnK6F9HV4jHHcoUk4KVhw,2825
|
|
16
|
+
pyntcli/commands/root.py,sha256=GijCi8hqe8sXEo6faWimlCmT8d782yjrw1IWJT5RAMk,3320
|
|
17
|
+
pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
|
|
18
|
+
pyntcli/commands/util.py,sha256=mi9c6Ex0ftpdY0jvI5BiBD2zwJD6RhrPQ2VyfxBZlA8,2793
|
|
19
|
+
pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
|
|
20
|
+
pyntcli/log/log.py,sha256=cWCdWmUaAwePwdhYDcgNMEG9d9RM34sGahxBCYEdv2Y,1069
|
|
21
|
+
pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
|
|
22
|
+
pyntcli/pynt_docker/container_utils.py,sha256=_Onn7loInzyJAG2-Uk6CGpsuRyelmUFHOvtJj4Uzi9A,175
|
|
23
|
+
pyntcli/pynt_docker/pynt_container.py,sha256=y4m8wZU16gqFPaMzEJKKHut4DbjPxr_du8g7I4-AcHk,8761
|
|
24
|
+
pyntcli/store/__init__.py,sha256=xuS9OB21F6B1sUx5XPGxz_6WpG6-KTMbuq50RrZS5OY,29
|
|
25
|
+
pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
|
|
26
|
+
pyntcli/store/store.py,sha256=Kf4IFCAu0i0DPVGgntrSYUiwz6kmW9HvItKnCT-MosE,1905
|
|
27
|
+
pyntcli/store/store_connector.py,sha256=w4LzcpRZesUZL1f63RmLlWEFRtJ6Y6rcS6PkkGtO4MA,357
|
|
28
|
+
pyntcli/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
29
|
+
pyntcli/transport/pynt_requests.py,sha256=KiEG3hNcwY7DLIJDCq-7LIPq54yYQcDBhHe3KhpqRTc,1563
|
|
30
|
+
pyntcli/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
31
|
+
pyntcli/ui/progress.py,sha256=RrnO_jJNunoyupylakmWmHOEPw3lh99OHpKBzL6OBiE,1008
|
|
32
|
+
pyntcli/ui/pynt_errors.py,sha256=UAr8OV5EM4zLhfWSmK_qss8nal2Ezo66Dk8ZMvR_RTs,546
|
|
33
|
+
pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
|
|
34
|
+
pyntcli/ui/ui_thread.py,sha256=OVTbiIFMg2KgxAvHf7yy86xGm4RVS2vj_VYZkMi-SRY,4956
|
|
35
|
+
tests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
|
|
36
|
+
tests/auth/test_login.py,sha256=juYxYZWfNmAuwm-ygGEF5gjzaR9LcimonDr7pN5vgLI,3209
|
|
37
|
+
tests/store/test_cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
|
|
38
|
+
pyntcli-0.1.75.dist-info/METADATA,sha256=RC4dmb_LHLW2n3oSNK5--zOSaOJBC2Hcm-7LQrUakiU,463
|
|
39
|
+
pyntcli-0.1.75.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
40
|
+
pyntcli-0.1.75.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
|
|
41
|
+
pyntcli-0.1.75.dist-info/top_level.txt,sha256=u9MDStwVHB7UG8PUcODeWCul_NvzL2EzoLvSlgwLHFs,30
|
|
42
|
+
pyntcli-0.1.75.dist-info/RECORD,,
|
tests/auth/test_login.py
CHANGED
|
@@ -10,7 +10,7 @@ import os
|
|
|
10
10
|
from cryptography.hazmat.primitives.asymmetric import rsa
|
|
11
11
|
from cryptography.hazmat.primitives import serialization
|
|
12
12
|
|
|
13
|
-
from pyntcli.auth.login import Login, Timeout, InvalidTokenInEnvVarsException, is_jwt_expired, should_login,
|
|
13
|
+
from pyntcli.auth.login import Login, Timeout, InvalidTokenInEnvVarsException, is_jwt_expired, should_login, PYNT_ID
|
|
14
14
|
from pyntcli.store import CredStore
|
|
15
15
|
|
|
16
16
|
|
|
@@ -22,8 +22,8 @@ class TestLogin():
|
|
|
22
22
|
yield
|
|
23
23
|
finally:
|
|
24
24
|
pass
|
|
25
|
-
|
|
26
|
-
def get_request_url_parameters(self, req: requests.PreparedRequest)
|
|
25
|
+
|
|
26
|
+
def get_request_url_parameters(self, req: requests.PreparedRequest):
|
|
27
27
|
u = req.url
|
|
28
28
|
parsed_url = urlparse(u)
|
|
29
29
|
return parsed_url.query
|
|
@@ -36,7 +36,7 @@ class TestLogin():
|
|
|
36
36
|
if self.login_request_cnt < 2:
|
|
37
37
|
resp.status_code = 404
|
|
38
38
|
return resp
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
resp.status_code = 200
|
|
41
41
|
resp._content = json.dumps({"token": "testToken"}).encode()
|
|
42
42
|
return resp
|
|
@@ -44,53 +44,51 @@ class TestLogin():
|
|
|
44
44
|
def test_login(self, mock_webbrowser, mock_sleep, mock_expanduser):
|
|
45
45
|
l = Login()
|
|
46
46
|
self.login_request_cnt = 0
|
|
47
|
-
with requests_mock.mock() as m:
|
|
47
|
+
with requests_mock.mock() as m:
|
|
48
48
|
m.add_matcher(self.poll_matcher)
|
|
49
|
-
l.login()
|
|
49
|
+
l.login()
|
|
50
50
|
|
|
51
51
|
assert self.login_request_cnt == 2
|
|
52
52
|
c = CredStore()
|
|
53
53
|
assert c.get("token") == {"token": "testToken"}
|
|
54
54
|
|
|
55
55
|
def test_login_timeout(self, mock_webbrowser, mock_sleep, mock_expanduser):
|
|
56
|
-
l = Login()
|
|
56
|
+
l = Login()
|
|
57
57
|
l.login_wait_period = 0
|
|
58
58
|
self.login_request_cnt = 0
|
|
59
59
|
with pytest.raises(Timeout):
|
|
60
60
|
with requests_mock.mock() as m:
|
|
61
61
|
m.add_matcher(self.poll_matcher)
|
|
62
62
|
l.get_token_using_request_id("some_id")
|
|
63
|
-
|
|
64
|
-
|
|
63
|
+
|
|
65
64
|
def test_is_jwt_expired(self):
|
|
66
65
|
|
|
67
66
|
private_key = rsa.generate_private_key(
|
|
68
67
|
public_exponent=65537,
|
|
69
68
|
key_size=2048
|
|
70
69
|
).private_bytes(encoding=serialization.Encoding.PEM,
|
|
71
|
-
format=serialization.PrivateFormat.PKCS8,
|
|
70
|
+
format=serialization.PrivateFormat.PKCS8,
|
|
72
71
|
encryption_algorithm=serialization.NoEncryption())
|
|
73
72
|
|
|
74
|
-
|
|
75
73
|
token_data = {
|
|
76
|
-
|
|
77
|
-
|
|
74
|
+
"exp": int((datetime.datetime.now() - datetime.timedelta(days=1)).timestamp())
|
|
75
|
+
}
|
|
78
76
|
|
|
79
77
|
token = jwt.encode(token_data, private_key.decode(), algorithm="RS256").decode("utf-8")
|
|
80
78
|
assert is_jwt_expired(token) == True
|
|
81
79
|
|
|
82
80
|
token_data = {
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
"exp": int((datetime.datetime.now() + datetime.timedelta(days=1)).timestamp())
|
|
82
|
+
}
|
|
85
83
|
|
|
86
84
|
token = jwt.encode(token_data, private_key.decode(), algorithm="RS256").decode("utf-8")
|
|
87
85
|
assert is_jwt_expired(token) == False
|
|
88
86
|
|
|
89
87
|
def test_login_using_env_vars(self, mocker, mock_expanduser):
|
|
90
88
|
creds = json.dumps({"token": {"refresh_token": "some data"}})
|
|
91
|
-
mocker.patch.dict(os.environ, {
|
|
92
|
-
assert should_login() == False
|
|
93
|
-
|
|
94
|
-
os.environ[
|
|
89
|
+
mocker.patch.dict(os.environ, {PYNT_ID: creds})
|
|
90
|
+
assert should_login() == False
|
|
91
|
+
|
|
92
|
+
os.environ[PYNT_ID] = "some bad credentials"
|
|
95
93
|
with pytest.raises(InvalidTokenInEnvVarsException):
|
|
96
94
|
should_login()
|
pyntcli-0.1.73.dist-info/RECORD
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
pyntcli/__init__.py,sha256=B2xptQoAZtCL_O_fLMSWF71JDtlCZp8jLmdtHyMdosE,23
|
|
2
|
-
pyntcli/main.py,sha256=cqratxd_ZJXLsP4xRbF2fmwj3Eo4kQ8WlbrwUtfZQ94,4125
|
|
3
|
-
pyntcli/analytics/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
pyntcli/analytics/send.py,sha256=ewNAKnn3KbKwfDuOasgAsSGbUWILLD8rPaXIAlLucnM,2507
|
|
5
|
-
pyntcli/auth/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
6
|
-
pyntcli/auth/login.py,sha256=WgF5r00bpM4c1__thzD6zCJ6207qxgtT0ixPvD1cEHA,5109
|
|
7
|
-
pyntcli/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
8
|
-
pyntcli/commands/burp.py,sha256=wd-HuNyj6v6IHk6x9-DAaqXcm1cQa-RA5FlxveBd6wA,10427
|
|
9
|
-
pyntcli/commands/command.py,sha256=tSjJj0fhQt2lCvtdu8H3IuiBlAllesx4f6ptNfuinTw,9435
|
|
10
|
-
pyntcli/commands/har.py,sha256=Iq0455umKvlcMxcU4l70-NIZh7Wovry3f76u68drmQ4,3654
|
|
11
|
-
pyntcli/commands/id_command.py,sha256=2J5oEa39uyBMMSCRHzuKh3_11CeUEYi7YLoBk1yuu_I,942
|
|
12
|
-
pyntcli/commands/listen.py,sha256=aANo5DwZ6_TAuXdJX3L8eDk9I6ompPAqtaUgxnEbR54,8536
|
|
13
|
-
pyntcli/commands/newman.py,sha256=_AspmTk98nY0Ct26WNK4fFgoYbqzmU90FfkygxJjgjY,4828
|
|
14
|
-
pyntcli/commands/postman.py,sha256=x5sPR-KaawKzAkLRK9vJXDzZ3sx9-6TuH6SNd5tnM4Y,4946
|
|
15
|
-
pyntcli/commands/pynt_cmd.py,sha256=NkzT8X4mI_fhzui_9KdAQXY5AnMGdoQkzDH6pcreLHU,2453
|
|
16
|
-
pyntcli/commands/root.py,sha256=FEf2gXvFyO_RZi6XzFakSVnOQw_sGBopY5SL5gldudg,3248
|
|
17
|
-
pyntcli/commands/sub_command.py,sha256=GF3-rE_qk2L4jGPFqHLm9SdGINmu3EakhjJTFyWjRms,374
|
|
18
|
-
pyntcli/commands/util.py,sha256=IREZvHYJ7wEth8ujOkk5ZXZ4UrUA7jDv134_UueED4s,2995
|
|
19
|
-
pyntcli/log/__init__.py,sha256=cOGwOYzMoshEbZiiasBGkj6wF0SBu3Jdpl-AuakDesw,19
|
|
20
|
-
pyntcli/log/log.py,sha256=EvqVVh0NwnTNjeiW6Pb5CZ_7FwNwZuVi7IhPodMeN-U,1039
|
|
21
|
-
pyntcli/pynt_docker/__init__.py,sha256=PQIOVxc7XXtMLfEX7ojgwf_Z3mmTllO3ZvzUZTPOxQY,30
|
|
22
|
-
pyntcli/pynt_docker/pynt_container.py,sha256=MJfd5CigTcEfH2WuGIi_DGFFkfSQwtm_hI0AZmFcdSs,8172
|
|
23
|
-
pyntcli/store/__init__.py,sha256=xuS9OB21F6B1sUx5XPGxz_6WpG6-KTMbuq50RrZS5OY,29
|
|
24
|
-
pyntcli/store/json_connector.py,sha256=UGs3uORw3iyn0YJ8kzab-veEZToA6d-ByXYuqEleWsA,560
|
|
25
|
-
pyntcli/store/store.py,sha256=Fbc7yxjht0EJ89eGF8eMgNQJ3sgYRTPmj2-sWQ5UUPs,1766
|
|
26
|
-
pyntcli/store/store_connector.py,sha256=w4LzcpRZesUZL1f63RmLlWEFRtJ6Y6rcS6PkkGtO4MA,357
|
|
27
|
-
pyntcli/transport/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
|
-
pyntcli/transport/pynt_requests.py,sha256=KiEG3hNcwY7DLIJDCq-7LIPq54yYQcDBhHe3KhpqRTc,1563
|
|
29
|
-
pyntcli/ui/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
30
|
-
pyntcli/ui/progress.py,sha256=RrnO_jJNunoyupylakmWmHOEPw3lh99OHpKBzL6OBiE,1008
|
|
31
|
-
pyntcli/ui/pynt_errors.py,sha256=UAr8OV5EM4zLhfWSmK_qss8nal2Ezo66Dk8ZMvR_RTs,546
|
|
32
|
-
pyntcli/ui/report.py,sha256=W-icPSZrGLOubXgam0LpOvHLl_aZg9Zx9qIkL8Ym5PE,1930
|
|
33
|
-
pyntcli/ui/ui_thread.py,sha256=OVTbiIFMg2KgxAvHf7yy86xGm4RVS2vj_VYZkMi-SRY,4956
|
|
34
|
-
tests/conftest.py,sha256=gToq5K74GtgeGQXjFvXSzMaE6axBYxAzcFG5XJPOXjI,427
|
|
35
|
-
tests/auth/test_login.py,sha256=M6JRFTQRZrL6M2-iph_r-aBSQMMiFDncQbVYeObBFYU,3296
|
|
36
|
-
tests/store/test_cred_store.py,sha256=_7-917EtNC9eKEumO2_lt-7KuDmCwOZFaowCm7DbA_A,254
|
|
37
|
-
pyntcli-0.1.73.dist-info/METADATA,sha256=YG6eADsoX_vyR3rTTkWvpkrKZeY8okAneTVRDvu3yZU,463
|
|
38
|
-
pyntcli-0.1.73.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
39
|
-
pyntcli-0.1.73.dist-info/entry_points.txt,sha256=kcGmqAxXDttNk2EPRcqunc_LTVp61gzakz0v-GEE2SY,43
|
|
40
|
-
pyntcli-0.1.73.dist-info/top_level.txt,sha256=u9MDStwVHB7UG8PUcODeWCul_NvzL2EzoLvSlgwLHFs,30
|
|
41
|
-
pyntcli-0.1.73.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|