pypomes-iam 0.3.4__tar.gz → 0.3.6__tar.gz
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.
Potentially problematic release.
This version of pypomes-iam might be problematic. Click here for more details.
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/PKG-INFO +1 -1
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/pyproject.toml +1 -1
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/src/pypomes_iam/iam_common.py +17 -104
- pypomes_iam-0.3.6/src/pypomes_iam/iam_pomes.py +509 -0
- pypomes_iam-0.3.6/src/pypomes_iam/iam_services.py +282 -0
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/src/pypomes_iam/jusbr_pomes.py +23 -17
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/src/pypomes_iam/keycloak_pomes.py +23 -17
- pypomes_iam-0.3.6/src/pypomes_iam/provider_pomes.py +146 -0
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/src/pypomes_iam/token_pomes.py +1 -1
- pypomes_iam-0.3.4/src/pypomes_iam/iam_pomes.py +0 -326
- pypomes_iam-0.3.4/src/pypomes_iam/iam_services.py +0 -243
- pypomes_iam-0.3.4/src/pypomes_iam/provider_pomes.py +0 -139
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/.gitignore +0 -0
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/LICENSE +0 -0
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/README.md +0 -0
- {pypomes_iam-0.3.4 → pypomes_iam-0.3.6}/src/pypomes_iam/__init__.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pypomes_iam
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.6
|
|
4
4
|
Summary: A collection of Python pomes, penyeach (IAM modules)
|
|
5
5
|
Project-URL: Homepage, https://github.com/TheWiseCoder/PyPomes-IAM
|
|
6
6
|
Project-URL: Bug Tracker, https://github.com/TheWiseCoder/PyPomes-IAM/issues
|
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
import json
|
|
2
1
|
import requests
|
|
3
2
|
import sys
|
|
4
|
-
from cachetools import Cache
|
|
5
3
|
from datetime import datetime
|
|
6
4
|
from enum import StrEnum
|
|
7
5
|
from logging import Logger
|
|
8
6
|
from pypomes_core import TZ_LOCAL, exc_format
|
|
9
7
|
from pypomes_crypto import crypto_jwk_convert
|
|
8
|
+
from threading import Lock
|
|
10
9
|
from typing import Any, Final
|
|
11
10
|
|
|
12
11
|
|
|
@@ -18,7 +17,8 @@ class IamServer(StrEnum):
|
|
|
18
17
|
IAM_KEYCLOAK = "iam-keycloak"
|
|
19
18
|
|
|
20
19
|
|
|
21
|
-
# the logger for IAM operations
|
|
20
|
+
# the logger for IAM service operations
|
|
21
|
+
# (used exclusively at the HTTP endpoint - all other functions receive the lgger as parameter)
|
|
22
22
|
__IAM_LOGGER: Logger | None = None
|
|
23
23
|
|
|
24
24
|
# registry structure:
|
|
@@ -53,11 +53,18 @@ __IAM_LOGGER: Logger | None = None
|
|
|
53
53
|
# }
|
|
54
54
|
_IAM_SERVERS: Final[dict[IamServer, dict[str, Any]]] = {}
|
|
55
55
|
|
|
56
|
+
# the lock protecting the data in '_IAM_SERVER'
|
|
57
|
+
# (because it is 'Final' and set at declaration time, it can be accessed through simple imports)
|
|
58
|
+
_iam_lock: Final[Lock] = Lock()
|
|
59
|
+
|
|
56
60
|
|
|
57
61
|
def _get_logger() -> Logger | None:
|
|
58
62
|
"""
|
|
59
63
|
Retrieve the registered logger for *IAM* operations.
|
|
60
64
|
|
|
65
|
+
This function is invoked exclusively from the HTTP endpoints.
|
|
66
|
+
All other functions receive the logger as parameter.
|
|
67
|
+
|
|
61
68
|
:return: the registered logger for *IAM* operations.
|
|
62
69
|
"""
|
|
63
70
|
return __IAM_LOGGER
|
|
@@ -175,11 +182,10 @@ def _get_user_data(iam_server: IamServer,
|
|
|
175
182
|
# initialize the return variable
|
|
176
183
|
result: dict[str, Any] | None = None
|
|
177
184
|
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
if
|
|
182
|
-
users: dict[str, dict[str, Any]] = cache.get("users")
|
|
185
|
+
users: dict[str, dict[str, Any]] = _get_iam_users(iam_server=iam_server,
|
|
186
|
+
errors=errors,
|
|
187
|
+
logger=logger)
|
|
188
|
+
if users:
|
|
183
189
|
result = users.get(user_id)
|
|
184
190
|
if not result:
|
|
185
191
|
result = {
|
|
@@ -256,9 +262,9 @@ def _get_iam_registry(iam_server: IamServer,
|
|
|
256
262
|
return result
|
|
257
263
|
|
|
258
264
|
|
|
259
|
-
def
|
|
265
|
+
def _get_iam_users(iam_server: IamServer,
|
|
260
266
|
errors: list[str] | None,
|
|
261
|
-
logger: Logger | None) ->
|
|
267
|
+
logger: Logger | None) -> dict[str, dict[str, Any]]:
|
|
262
268
|
"""
|
|
263
269
|
Retrieve the cache storage in *iam_server*'s registry.
|
|
264
270
|
|
|
@@ -270,97 +276,4 @@ def _get_iam_cache(iam_server: IamServer,
|
|
|
270
276
|
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
271
277
|
errors=errors,
|
|
272
278
|
logger=logger)
|
|
273
|
-
return registry["cache"] if registry else None
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
def _post_for_token(iam_server: IamServer,
|
|
277
|
-
body_data: dict[str, Any],
|
|
278
|
-
errors: list[str] | None,
|
|
279
|
-
logger: Logger | None) -> dict[str, Any] | None:
|
|
280
|
-
"""
|
|
281
|
-
Send a POST request to obtain the authentication token data, and return the data received.
|
|
282
|
-
|
|
283
|
-
For token acquisition, *body_data* will have the attributes:
|
|
284
|
-
- "grant_type": "authorization_code"
|
|
285
|
-
- "code": <16-character-random-code>
|
|
286
|
-
- "redirect_uri": <redirect-uri>
|
|
287
|
-
|
|
288
|
-
For token refresh, *body_data* will have the attributes:
|
|
289
|
-
- "grant_type": "refresh_token"
|
|
290
|
-
- "refresh_token": <current-refresh-token>
|
|
291
|
-
|
|
292
|
-
For token exchange, *body_data* will have the attributes:
|
|
293
|
-
- "grant_type": "urn:ietf:params:oauth:grant-type:token-exchange",
|
|
294
|
-
- "subject_token": <token-to-be-exchanged>,
|
|
295
|
-
- "subject_token_type": "urn:ietf:params:oauth:token-type:access_token",
|
|
296
|
-
- "requested_token_type": "urn:ietf:params:oauth:token-type:access_token",
|
|
297
|
-
- "audience": <client-id>,
|
|
298
|
-
- "subject_issuer": "oidc"
|
|
299
|
-
|
|
300
|
-
These attributes are then added to *body_data*:
|
|
301
|
-
- "client_id": <client-id>,
|
|
302
|
-
- "client_secret": <client-secret>,
|
|
303
|
-
|
|
304
|
-
If the operation is successful, the token data is stored in the registry.
|
|
305
|
-
Otherwise, *errors* will contain the appropriate error message.
|
|
306
|
-
|
|
307
|
-
:param iam_server: the reference registered *IAM* server
|
|
308
|
-
:param body_data: the data to send in the body of the request
|
|
309
|
-
:param errors: incidental errors
|
|
310
|
-
:param logger: optional logger
|
|
311
|
-
:return: the access token obtained, or *None* if error
|
|
312
|
-
"""
|
|
313
|
-
# initialize the return variable
|
|
314
|
-
result: dict[str, Any] | None = None
|
|
315
|
-
|
|
316
|
-
# PBTAIN THE iam SERVER'S REGISTRY
|
|
317
|
-
registry: dict[str, Any] = _get_iam_registry(iam_server=iam_server,
|
|
318
|
-
errors=errors,
|
|
319
|
-
logger=logger)
|
|
320
|
-
err_msg: str | None = None
|
|
321
|
-
if registry:
|
|
322
|
-
# complete the data to send in body of request
|
|
323
|
-
body_data["client_id"] = registry["client-id"]
|
|
324
|
-
client_secret: str = registry["client-secret"]
|
|
325
|
-
if client_secret:
|
|
326
|
-
body_data["client_secret"] = client_secret
|
|
327
|
-
|
|
328
|
-
# obtain the token
|
|
329
|
-
url: str = registry["base-url"] + "/protocol/openid-connect/token"
|
|
330
|
-
if logger:
|
|
331
|
-
logger.debug(msg=f"POST '{url}', data {json.dumps(obj=body_data,
|
|
332
|
-
ensure_ascii=False)}")
|
|
333
|
-
try:
|
|
334
|
-
# typical return on a token request:
|
|
335
|
-
# {
|
|
336
|
-
# "token_type": "Bearer",
|
|
337
|
-
# "access_token": <str>,
|
|
338
|
-
# "expires_in": <number-of-seconds>,
|
|
339
|
-
# "refresh_token": <str>,
|
|
340
|
-
# "refesh_expires_in": <number-of-seconds>
|
|
341
|
-
# }
|
|
342
|
-
response: requests.Response = requests.post(url=url,
|
|
343
|
-
data=body_data)
|
|
344
|
-
if response.status_code == 200:
|
|
345
|
-
# request succeeded
|
|
346
|
-
if logger:
|
|
347
|
-
logger.debug(msg=f"POST success, status {response.status_code}")
|
|
348
|
-
result = response.json()
|
|
349
|
-
else:
|
|
350
|
-
# request resulted in error
|
|
351
|
-
err_msg = f"POST failure, status {response.status_code}, reason '{response.reason}'"
|
|
352
|
-
if hasattr(response, "content") and response.content:
|
|
353
|
-
err_msg += f", content '{response.content}'"
|
|
354
|
-
if logger:
|
|
355
|
-
logger.error(msg=err_msg)
|
|
356
|
-
except Exception as e:
|
|
357
|
-
# the operation raised an exception
|
|
358
|
-
err_msg = exc_format(exc=e,
|
|
359
|
-
exc_info=sys.exc_info())
|
|
360
|
-
if logger:
|
|
361
|
-
logger.error(msg=err_msg)
|
|
362
|
-
|
|
363
|
-
if err_msg and isinstance(errors, list):
|
|
364
|
-
errors.append(err_msg)
|
|
365
|
-
|
|
366
|
-
return result
|
|
279
|
+
return registry["cache"]["users"] if registry else None
|