pypomes-iam 0.5.8__tar.gz → 0.6.0__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.

@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypomes_iam
3
- Version: 0.5.8
3
+ Version: 0.6.0
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
@@ -6,7 +6,7 @@ build-backend = "hatchling.build"
6
6
 
7
7
  [project]
8
8
  name = "pypomes_iam"
9
- version = "0.5.8"
9
+ version = "0.6.0"
10
10
  authors = [
11
11
  { name="GT Nunes", email="wisecoder01@gmail.com" }
12
12
  ]
@@ -6,7 +6,7 @@ from .iam_common import (
6
6
  IamServer, IamParam
7
7
  )
8
8
  from .iam_pomes import (
9
- iam_setup, iam_get_token
9
+ iam_setup, iam_get_env_parameters, iam_get_token
10
10
  )
11
11
  from .iam_services import (
12
12
  jwt_required, logger_register
@@ -25,7 +25,7 @@ __all__ = [
25
25
  # iam_commons
26
26
  "IamServer", "IamParam",
27
27
  # iam_pomes
28
- "iam_setup", "iam_get_token",
28
+ "iam_setup", "iam_get_env_parameters", "iam_get_token",
29
29
  # iam_services
30
30
  "jwt_required", "logger_register",
31
31
  # provider_pomes
@@ -3,10 +3,7 @@ import sys
3
3
  from datetime import datetime
4
4
  from enum import StrEnum, auto
5
5
  from logging import Logger
6
- from pypomes_core import (
7
- APP_PREFIX, TZ_LOCAL,
8
- env_get_int, env_get_str, env_get_enum, env_get_enums, exc_format
9
- )
6
+ from pypomes_core import TZ_LOCAL, exc_format
10
7
  from pypomes_crypto import crypto_jwk_convert
11
8
  from threading import RLock
12
9
  from typing import Any, Final
@@ -16,7 +13,7 @@ class IamServer(StrEnum):
16
13
  """
17
14
  Supported IAM servers.
18
15
  """
19
- JUSRBR = auto()
16
+ JUSBR = auto()
20
17
  KEYCLOAK = auto()
21
18
 
22
19
 
@@ -57,85 +54,37 @@ class UserParam(StrEnum):
57
54
  REDIRECT_URI = "redirect-uri"
58
55
 
59
56
 
60
- def __get_iam_data() -> dict[IamServer, dict[IamParam, Any]]:
61
- """
62
- Establish the configuration data for select *IAM* servers, from environment variables.
63
-
64
- The preferred way to specify configuration parameters is dynamically with *iam_setup()*;.
65
- Specifying configuration parameters with environment variables can be done in two ways:
66
-
67
- 1. for a single *IAM* server, specify the data set
68
- - *<APP_PREFIX>_IAM_SERVER* (required, one of *jusbr*, *keycloak*)
69
- - *<APP_PREFIX>_IAM_ADMIN_ID* (optional, needed only if administrative duties are performed)
70
- - *<APP_PREFIX>_IAM_ADMIN_PWD* (optional, needed only if administrative duties are performed)
71
- - *<APP_PREFIX>_IAM_CLIENT_ID* (required)
72
- - *<APP_PREFIX>_IAM_CLIENT_REALM* (required)
73
- - *<APP_PREFIX>_IAM_CLIENT_SECRET* (required)
74
- - *<APP_PREFIX>_IAM_ENDPOINT_CALLBACK* (optional)
75
- - *<APP_PREFIX>_IAM_ENDPOINT_LOGIN* (optional)
76
- - *<APP_PREFIX>_IAM_ENDPOINT_LOGOUT* (optional)
77
- - *<APP_PREFIX>_IAM_ENDPOINT_TOKEN* (optional)
78
- - *<APP_PREFIX>_IAM_ENDPOINT_EXCHANGE* (optional)
79
- - *<APP_PREFIX>_IAM_LOGIN_TIMEOUT* (optional, defaults to no timeout)
80
- - *<APP_PREFIX>_IAM_PK_LIFETIME* (optional, defaults to non-terminating lifetime)
81
- - *<APP_PREFIX>_IAM_RECIPIENT_ATTR* (required)
82
- - *<APP_PREFIX>_IAM_URL_BASE* (required)
83
-
84
- 2. the parameters *PUBLIC_KEY*, *PK_EXPIRATION*, and *USERS* cannot be assigned values,
85
- as they are reserved for internal use
86
-
87
- 3. for multiple *IAM* servers, specify a comma-separated list of servers in
88
- *<APP_PREFIX>_IAM_SERVERS*, and for each server, specify the data set above,
89
- respectively replacing *_IAM_* with *_JUSBR_* or *_KEYCLOAK_*, for the servers listed above
90
-
91
- :return: the configuration data for the selected *IAM* servers
92
- """
93
- # initialize the return valiable
94
- result: dict[IamServer, dict[IamParam, Any]] = {}
95
-
96
- servers: list[IamServer] = []
97
- single_server: IamServer = env_get_enum(key=f"{APP_PREFIX}_IAM_SERVER",
98
- enum_class=IamServer)
99
- if single_server:
100
- default_setup: bool = True
101
- servers.append(single_server)
102
- else:
103
- default_setup: bool = False
104
- multi_servers: list[IamServer] = env_get_enums(key=f"{APP_PREFIX}_IAM_SERVERS",
105
- enum_class=IamServer)
106
- if multi_servers:
107
- servers.extend(multi_servers)
108
-
109
- for server in servers:
110
- if default_setup:
111
- prefix: str = "IAM"
112
- default_setup = False
113
- else:
114
- prefix: str = server
115
- result[server] = {
116
- IamParam.ADMIN_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_ADMIN_ID"),
117
- IamParam.ADMIN_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_ADMIN_PWD"),
118
- IamParam.CLIENT_ID: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_ID"),
119
- IamParam.CLIENT_REALM: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_REALM"),
120
- IamParam.CLIENT_SECRET: env_get_str(key=f"{APP_PREFIX}_{prefix}_CLIENT_SECRET"),
121
- IamParam.LOGIN_TIMEOUT: env_get_int(key=f"{APP_PREFIX}_{prefix}_CLIENT_TIMEOUT"),
122
- IamParam.ENDPOINT_CALLBACK: env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_CALLBACK"),
123
- IamParam.ENDPOINT_LOGIN: env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_LOGIN"),
124
- IamParam.ENDPOINT_LOGOUT: env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_LOGOUT"),
125
- IamParam.ENDPOINT_TOKEN: env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_TOKEN"),
126
- IamParam.ENDPOINT_EXCHANGE: env_get_str(key=f"{APP_PREFIX}_{prefix}_ENDPOINT_EXCHANGE"),
127
- IamParam.PK_LIFETIME: env_get_str(key=f"{APP_PREFIX}_{prefix}_PK_LIFETIME"),
128
- IamParam.RECIPIENT_ATTR: env_get_str(key=f"{APP_PREFIX}_{prefix}_RECIPIENT_ATTR"),
129
- IamParam.URL_BASE: env_get_str(key=f"{APP_PREFIX}_{prefix}_URL_BASE")
130
- }
131
-
132
- return result
133
-
57
+ # The configuration parameters for the IAM servers are specified dynamically dynamically with *iam_setup()*
58
+ # Specifying configuration parameters with environment variables can be done in two ways:
59
+ #
60
+ # 1. for a single *IAM* server, specify the data set
61
+ # - *<APP_PREFIX>_IAM_ADMIN_ID* (optional, needed only if administrative duties are performed)
62
+ # - *<APP_PREFIX>_IAM_ADMIN_PWD* (optional, needed only if administrative duties are performed)
63
+ # - *<APP_PREFIX>_IAM_CLIENT_ID* (required)
64
+ # - *<APP_PREFIX>_IAM_CLIENT_REALM* (required)
65
+ # - *<APP_PREFIX>_IAM_CLIENT_SECRET* (required)
66
+ # - *<APP_PREFIX>_IAM_ENDPOINT_CALLBACK* (optional)
67
+ # - *<APP_PREFIX>_IAM_ENDPOINT_LOGIN* (optional)
68
+ # - *<APP_PREFIX>_IAM_ENDPOINT_LOGOUT* (optional)
69
+ # - *<APP_PREFIX>_IAM_ENDPOINT_TOKEN* (optional)
70
+ # - *<APP_PREFIX>_IAM_ENDPOINT_EXCHANGE* (optional)
71
+ # - *<APP_PREFIX>_IAM_LOGIN_TIMEOUT* (optional, defaults to no timeout)
72
+ # - *<APP_PREFIX>_IAM_PK_LIFETIME* (optional, defaults to non-terminating lifetime)
73
+ # - *<APP_PREFIX>_IAM_RECIPIENT_ATTR* (required)
74
+ # - *<APP_PREFIX>_IAM_URL_BASE* (required)
75
+ #
76
+ # 2. for multiple *IAM* servers, specify the data set above for each server,
77
+ # respectively replacing *IAM* with a name in *IamServer* (currently, *JUSBR* and *KEYCLOAK* are supported).
78
+ #
79
+ # 3. the parameters *PUBLIC_KEY*, *PK_EXPIRATION*, and *USERS* cannot be assigned values,
80
+ # as they are reserved for internal use
134
81
 
135
82
  # registry structure:
136
83
  # { <IamServer>:
137
84
  # {
138
85
  # "base-url": <str>,
86
+ # "admin-id": <str>,
87
+ # "admin-secret": <str>,
139
88
  # "client-id": <str>,
140
89
  # "client-secret": <str>,
141
90
  # "client-realm": <str,
@@ -162,7 +111,7 @@ def __get_iam_data() -> dict[IamServer, dict[IamParam, Any]]:
162
111
  # },
163
112
  # ...
164
113
  # }
165
- _IAM_SERVERS: Final[dict[IamServer, dict[IamParam, Any]]] = __get_iam_data()
114
+ _IAM_SERVERS: Final[dict[IamServer, dict[IamParam, Any]]] = {}
166
115
 
167
116
 
168
117
  # the lock protecting the data in '_IAM_SERVERS'
@@ -186,7 +135,7 @@ def _iam_server_from_endpoint(endpoint: str,
186
135
 
187
136
  for iam_server in _IAM_SERVERS:
188
137
  if endpoint.startswith(iam_server):
189
- result = IamServer.JUSRBR
138
+ result = iam_server
190
139
  break
191
140
 
192
141
  if not result:
@@ -408,21 +357,15 @@ def _get_iam_registry(iam_server: IamServer,
408
357
  :param logger: optional logger
409
358
  :return: the registry associated with *iam_server*, or *None* if the server is unknown
410
359
  """
411
- # declare the return variable
412
- result: dict[str, Any] | None
413
-
414
- match iam_server:
415
- case IamServer.JUSRBR:
416
- result = _IAM_SERVERS[IamServer.JUSRBR]
417
- case IamServer.KEYCLOAK:
418
- result = _IAM_SERVERS[IamServer.KEYCLOAK]
419
- case _:
420
- result = None
421
- msg = f"Unknown IAM server '{iam_server}'"
422
- if logger:
423
- logger.error(msg=msg)
424
- if isinstance(errors, list):
425
- errors.append(msg)
360
+ # assign the return variable
361
+ result: dict[str, Any] = _IAM_SERVERS.get(iam_server)
362
+
363
+ if not result:
364
+ msg = f"Unknown IAM server '{iam_server}'"
365
+ if logger:
366
+ logger.error(msg=msg)
367
+ if isinstance(errors, list):
368
+ errors.append(msg)
426
369
 
427
370
  return result
428
371
 
@@ -1,5 +1,6 @@
1
1
  from flask import Flask
2
2
  from logging import Logger
3
+ from pypomes_core import APP_PREFIX, env_get_int, env_get_str
3
4
  from typing import Any
4
5
 
5
6
  from .iam_common import (
@@ -16,17 +17,17 @@ def iam_setup(flask_app: Flask,
16
17
  base_url: str,
17
18
  client_id: str,
18
19
  client_realm: str,
20
+ client_secret: str | None,
19
21
  recipient_attribute: str,
20
- client_secret: str = None,
21
- login_timeout: int = None,
22
22
  admin_id: str = None,
23
23
  admin_secret: str = None,
24
+ login_timeout: int = None,
24
25
  public_key_lifetime: int = None,
25
26
  callback_endpoint: str = None,
27
+ exchange_endpoint: str = None,
26
28
  login_endpoint: str = None,
27
29
  logout_endpoint: str = None,
28
- token_endpoint: str = None,
29
- exchange_endpoint: str = None) -> None:
30
+ token_endpoint: str = None) -> None:
30
31
  """
31
32
  Establish the provided parameters for configuring the *IAM* server *iam_server*.
32
33
 
@@ -43,17 +44,17 @@ def iam_setup(flask_app: Flask,
43
44
  :param base_url: base URL to request services
44
45
  :param client_id: the client's identification with the *IAM* server
45
46
  :param client_realm: the client realm
46
- :param recipient_attribute: attribute in the token's payload holding the token's subject
47
47
  :param client_secret: the client's password with the *IAM* server
48
- :param login_timeout: timeout for login authentication (in seconds,defaults to no timeout)
48
+ :param recipient_attribute: attribute in the token's payload holding the token's subject
49
49
  :param admin_id: identifies the realm administrator
50
50
  :param admin_secret: password for the realm administrator
51
+ :param login_timeout: timeout for login authentication (in seconds,defaults to no timeout)
51
52
  :param public_key_lifetime: how long to use *IAM* server's public key, before refreshing it (in seconds)
52
53
  :param callback_endpoint: endpoint for the callback from the front end
54
+ :param exchange_endpoint: endpoint for requesting token exchange
53
55
  :param login_endpoint: endpoint for redirecting user to the *IAM* server's login page
54
56
  :param logout_endpoint: endpoint for terminating user access
55
57
  :param token_endpoint: endpoint for retrieving authentication token
56
- :param exchange_endpoint: endpoint for requesting token exchange
57
58
  """
58
59
 
59
60
  # configure the Keycloak registry
@@ -63,18 +64,15 @@ def iam_setup(flask_app: Flask,
63
64
  IamParam.CLIENT_ID: client_id,
64
65
  IamParam.CLIENT_REALM: client_realm,
65
66
  IamParam.CLIENT_SECRET: client_secret,
66
- IamParam.LOGIN_TIMEOUT: login_timeout,
67
67
  IamParam.RECIPIENT_ATTR: recipient_attribute,
68
+ IamParam.ADMIN_ID: admin_id,
69
+ IamParam.ADMIN_SECRET: admin_secret,
70
+ IamParam.LOGIN_TIMEOUT: login_timeout,
71
+ IamParam.PK_LIFETIME: public_key_lifetime,
68
72
  IamParam.PK_EXPIRATION: 0,
69
73
  IamParam.PUBLIC_KEY: None,
70
74
  IamParam.USERS: {}
71
75
  }
72
- if admin_id and admin_secret:
73
- IamParam.ADMIN_ID = admin_id
74
- IamParam.ADMIN_SECRET = admin_secret
75
-
76
- if public_key_lifetime:
77
- IamParam.PK_LIFETIME = public_key_lifetime
78
76
 
79
77
  # establish the endpoints
80
78
  if callback_endpoint:
@@ -104,6 +102,34 @@ def iam_setup(flask_app: Flask,
104
102
  methods=["POST"])
105
103
 
106
104
 
105
+ def iam_get_env_parameters(iam_prefix: str = None) -> dict[str, Any]:
106
+ """
107
+ Retrieve the set parameters for a *IAM* server from the environment.
108
+
109
+ the parameters are returned ready to be used as a '**kwargs' parameter set in a call to *iam_setup()*,
110
+ and sorted in the order appropriate to use them instead with a '*args' parameter set.
111
+
112
+ :param iam_prefix: the prefix classifying the parameters
113
+ :return: the sorted parameters classified by *prefix*
114
+ """
115
+ return {
116
+ "base_url": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_URL_AUTH_BASE"),
117
+ "client_id": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_CLIENT_ID"),
118
+ "client_realm": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_CLIENT_REALM"),
119
+ "client_secret": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_CLIENT_SECRET"),
120
+ "recipient_attribute": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_RECIPIENT_ATTR"),
121
+ "admin_id": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ADMIN_ID"),
122
+ "admin_secret": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ADMIN_SECRET"),
123
+ "login_timeout": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_LOGIN_TIMEOUT"),
124
+ "public_key_lifetime": env_get_int(key=f"{APP_PREFIX}_{iam_prefix}_PUBLIC_KEY_LIFETIME"),
125
+ "callback_endpoint": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ENDPOINT_CALLBACK"),
126
+ "exchange_endpoint": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ENDPOINT_EXCHANGE"),
127
+ "login_endpoint": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ENDPOINT_LOGIN"),
128
+ "logout_endpoint": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ENDPOINT_LOGOUT"),
129
+ "token_endpoint": env_get_str(key=f"{APP_PREFIX}_{iam_prefix}_ENDPOINT_TOKEN")
130
+ }
131
+
132
+
107
133
  def iam_get_token(iam_server: IamServer,
108
134
  user_id: str,
109
135
  errors: list[str] = None,
File without changes
File without changes
File without changes
File without changes