cycode 3.23.1.dev2__py3-none-any.whl → 3.24.1.dev1__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.
- cycode/__init__.py +1 -1
- cycode/cyclient/base_token_auth_client.py +22 -1
- {cycode-3.23.1.dev2.dist-info → cycode-3.24.1.dev1.dist-info}/METADATA +1 -1
- {cycode-3.23.1.dev2.dist-info → cycode-3.24.1.dev1.dist-info}/RECORD +7 -7
- {cycode-3.23.1.dev2.dist-info → cycode-3.24.1.dev1.dist-info}/WHEEL +0 -0
- {cycode-3.23.1.dev2.dist-info → cycode-3.24.1.dev1.dist-info}/entry_points.txt +0 -0
- {cycode-3.23.1.dev2.dist-info → cycode-3.24.1.dev1.dist-info}/licenses/LICENCE +0 -0
cycode/__init__.py
CHANGED
|
@@ -5,4 +5,4 @@ import time as _time
|
|
|
5
5
|
# end-to-end scan duration from the moment the user actually triggered it.
|
|
6
6
|
_BOOT_WALL: float = _time.time()
|
|
7
7
|
|
|
8
|
-
__version__ = '3.
|
|
8
|
+
__version__ = '3.24.1.dev1' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
import time
|
|
1
3
|
from abc import ABC, abstractmethod
|
|
2
4
|
from threading import Lock
|
|
3
5
|
from typing import Any, Optional
|
|
@@ -5,6 +7,7 @@ from typing import Any, Optional
|
|
|
5
7
|
import arrow
|
|
6
8
|
from requests import Response
|
|
7
9
|
|
|
10
|
+
from cycode.cli.exceptions.custom_exceptions import HttpUnauthorizedError
|
|
8
11
|
from cycode.cli.user_settings.credentials_manager import CredentialsManager
|
|
9
12
|
from cycode.cli.user_settings.jwt_creator import JwtCreator
|
|
10
13
|
from cycode.cyclient.cycode_client import CycodeClient
|
|
@@ -15,6 +18,11 @@ _NGINX_PLAIN_ERRORS = [
|
|
|
15
18
|
b'JWT Token validation failed',
|
|
16
19
|
]
|
|
17
20
|
|
|
21
|
+
# Identity provider brute-force protection rejects logins for the same user that land within
|
|
22
|
+
# milliseconds of each other, so when several processes mint at once all but one are refused.
|
|
23
|
+
_MINT_CONFLICT_RETRY_MIN_MS = 50
|
|
24
|
+
_MINT_CONFLICT_RETRY_SPREAD_MS = 100
|
|
25
|
+
|
|
18
26
|
|
|
19
27
|
class BaseTokenAuthClient(CycodeClient, ABC):
|
|
20
28
|
"""Base client for token-based authentication flows with cached JWTs."""
|
|
@@ -49,7 +57,20 @@ class BaseTokenAuthClient(CycodeClient, ABC):
|
|
|
49
57
|
self._load_token_from_disk()
|
|
50
58
|
if self._has_valid_token():
|
|
51
59
|
return
|
|
52
|
-
|
|
60
|
+
|
|
61
|
+
try:
|
|
62
|
+
self.refresh_access_token()
|
|
63
|
+
except HttpUnauthorizedError:
|
|
64
|
+
# Processes sharing one cached token all expire at the same instant, so a burst of
|
|
65
|
+
# them mints together and the identity provider refuses all but the first as a
|
|
66
|
+
# too-fast login. The winner persists a usable token, so prefer re-reading it over
|
|
67
|
+
# minting again. The wait is randomized to keep the losers from colliding a second
|
|
68
|
+
# time. A genuinely invalid token still raises on the retry.
|
|
69
|
+
time.sleep((_MINT_CONFLICT_RETRY_MIN_MS + secrets.randbelow(_MINT_CONFLICT_RETRY_SPREAD_MS)) / 1000)
|
|
70
|
+
self._load_token_from_disk()
|
|
71
|
+
if self._has_valid_token():
|
|
72
|
+
return
|
|
73
|
+
self.refresh_access_token()
|
|
53
74
|
|
|
54
75
|
def _has_valid_token(self) -> bool:
|
|
55
76
|
return self._access_token is not None and self._expires_in is not None and arrow.utcnow() < self._expires_in
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
cycode/__init__.py,sha256=
|
|
1
|
+
cycode/__init__.py,sha256=I-iQNkQ_J9hG3RTJGySCJrSBiqdRU1jt3DxF46X8qaw,396
|
|
2
2
|
cycode/__main__.py,sha256=Z3bD5yrA7yPvAChcADQrqCaZd0ChGI1gdiwALwbWJ6U,104
|
|
3
3
|
cycode/cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
cycode/cli/app.py,sha256=AlR2durAEbsa47PDfIj7JtMvJDWA_Dq6wPtVuMJYSCs,10250
|
|
@@ -199,7 +199,7 @@ cycode/cyclient/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
199
199
|
cycode/cyclient/ai_security_manager_client.py,sha256=90fvqH_h2-dI9YqQ6oo4YBfa777p5mSr8JSM1ZZJJcE,5486
|
|
200
200
|
cycode/cyclient/ai_security_manager_service_config.py,sha256=83pQzgOb93JW6E-dznJkI4c0NEXmQRlx9YZKMmjVwp8,808
|
|
201
201
|
cycode/cyclient/auth_client.py,sha256=TwbmZ358Ancf-Q-IZolvfljZ8691_6botsqd0R0PLPk,2105
|
|
202
|
-
cycode/cyclient/base_token_auth_client.py,sha256=
|
|
202
|
+
cycode/cyclient/base_token_auth_client.py,sha256=V907nf_1TvtfzwDal2bAgmXvgqaaX_ERUvSRipujz30,5490
|
|
203
203
|
cycode/cyclient/cli_activation_client.py,sha256=QaATFVABf0vQ6cTU_dCN9UT6fUkJf5qciaK8W7gQDrc,419
|
|
204
204
|
cycode/cyclient/client_creator.py,sha256=-bsOT7M28yx-WT1UhSzENY8N9EgoQIv48Smrr9izQTI,2849
|
|
205
205
|
cycode/cyclient/config.py,sha256=Le3YYp7LyclTwS4vonuFipfRA1qhyC28_muUtxpnImc,1387
|
|
@@ -217,8 +217,8 @@ cycode/cyclient/report_client.py,sha256=Scq30NeJPzgXv0hPLO1U05AdE9i_2iu6cIrSKpEJ
|
|
|
217
217
|
cycode/cyclient/scan_client.py,sha256=DqAZ7u6Z_cvw9A9RlLkAQUgLRwPCCAsUq5U9umt4F7Y,16955
|
|
218
218
|
cycode/cyclient/scan_config_base.py,sha256=mXsPZGYCtp85rv5GIige40yQZXuRcEKUW-VQJ0vgFzk,1201
|
|
219
219
|
cycode/logger.py,sha256=EfZGRK6VC5rE_LAjIcRrHFiQCueylCDXoG6bvGkrIME,2111
|
|
220
|
-
cycode-3.
|
|
221
|
-
cycode-3.
|
|
222
|
-
cycode-3.
|
|
223
|
-
cycode-3.
|
|
224
|
-
cycode-3.
|
|
220
|
+
cycode-3.24.1.dev1.dist-info/METADATA,sha256=Q_CfNk0EX1rgA3ndLHucRys9j-AqsPED4kmveNVm5eY,93687
|
|
221
|
+
cycode-3.24.1.dev1.dist-info/WHEEL,sha256=zp0Cn7JsFoX2ATtOhtaFYIiE2rmFAD4OcMhtUki8W3U,88
|
|
222
|
+
cycode-3.24.1.dev1.dist-info/entry_points.txt,sha256=iDcVJM8ByLElVgvBgtYxDjw1kT7O8Mo0LcWZIT5L3Ig,45
|
|
223
|
+
cycode-3.24.1.dev1.dist-info/licenses/LICENCE,sha256=2Wx4N6mD_4xB7-E3hPkZ3MPhpJy__k_I8MaCSO-PDRo,1068
|
|
224
|
+
cycode-3.24.1.dev1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|