pypomes-iam 0.3.8__tar.gz → 0.4.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pypomes_iam
3
- Version: 0.3.8
3
+ Version: 0.4.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.3.8"
9
+ version = "0.4.0"
10
10
  authors = [
11
11
  { name="GT Nunes", email="wisecoder01@gmail.com" }
12
12
  ]
@@ -1,8 +1,11 @@
1
1
  from .iam_pomes import (
2
- IamServer, logger_register,
2
+ IamServer,
3
3
  login_callback, token_exchange,
4
4
  user_login, user_logout, user_token
5
5
  )
6
+ from .iam_services import (
7
+ logger_register
8
+ )
6
9
  from .jusbr_pomes import (
7
10
  jusbr_setup, jusbr_get_token
8
11
  )
@@ -18,9 +21,11 @@ from .token_pomes import (
18
21
 
19
22
  __all__ = [
20
23
  # iam_pomes
21
- "IamServer", "logger_register",
24
+ "IamServer",
22
25
  "login_callback", "token_exchange",
23
26
  "user_login", "user_logout", "user_token",
27
+ # iam_services
28
+ "logger_register",
24
29
  # jusbr_pomes
25
30
  "jusbr_setup", "jusbr_get_token",
26
31
  # keycloak_pomes
@@ -17,10 +17,6 @@ class IamServer(StrEnum):
17
17
  IAM_KEYCLOAK = "iam-keycloak"
18
18
 
19
19
 
20
- # the logger for IAM service operations
21
- # (used exclusively at the HTTP endpoint - all other functions receive the lgger as parameter)
22
- __IAM_LOGGER: Logger | None = None
23
-
24
20
  # registry structure:
25
21
  # { <IamServer>:
26
22
  # {
@@ -58,28 +54,6 @@ _IAM_SERVERS: Final[dict[IamServer, dict[str, Any]]] = {}
58
54
  _iam_lock: Final[Lock] = Lock()
59
55
 
60
56
 
61
- def _get_logger() -> Logger | None:
62
- """
63
- Retrieve the registered logger for *IAM* operations.
64
-
65
- This function is invoked exclusively from the HTTP endpoints.
66
- All other functions receive the logger as parameter.
67
-
68
- :return: the registered logger for *IAM* operations.
69
- """
70
- return __IAM_LOGGER
71
-
72
-
73
- def _register_logger(logger: Logger) -> None:
74
- """
75
- Register the logger for *IAM* operations
76
-
77
- :param logger: the logger to be rergistered
78
- """
79
- global __IAM_LOGGER
80
- __IAM_LOGGER = logger
81
-
82
-
83
57
  def _get_public_key(iam_server: IamServer,
84
58
  errors: list[str] | None,
85
59
  logger: Logger | None) -> str:
@@ -10,21 +10,12 @@ from typing import Any
10
10
 
11
11
  from .iam_common import (
12
12
  IamServer, _iam_lock,
13
- _register_logger, _get_iam_users, _get_iam_registry,
13
+ _get_iam_users, _get_iam_registry,
14
14
  _get_login_timeout, _get_user_data, _get_public_key
15
15
  )
16
16
  from .token_pomes import token_validate
17
17
 
18
18
 
19
- def logger_register(logger: Logger) -> None:
20
- """
21
- Register the logger for IAM operations.
22
-
23
- :param logger: the logger to be registered
24
- """
25
- _register_logger(logger=logger)
26
-
27
-
28
19
  def user_login(iam_server: IamServer,
29
20
  args: dict[str, Any],
30
21
  errors: list[str] = None,
@@ -3,15 +3,26 @@ from flask import Request, Response, request, jsonify
3
3
  from logging import Logger
4
4
  from typing import Any
5
5
 
6
- from .iam_common import (
7
- IamServer, _iam_lock,
8
- _get_logger, _get_iam_server
9
- )
6
+ from .iam_common import IamServer, _iam_lock, _get_iam_server
10
7
  from .iam_pomes import (
11
8
  user_login, user_logout,
12
9
  user_token, token_exchange, login_callback
13
10
  )
14
11
 
12
+ # the logger for IAM service operations
13
+ # (used exclusively at the HTTP endpoints - all other functions receive the logger as parameter)
14
+ __IAM_LOGGER: Logger | None = None
15
+
16
+
17
+ def logger_register(logger: Logger) -> None:
18
+ """
19
+ Register the logger for HTTP services.
20
+
21
+ :param logger: the logger to be registered
22
+ """
23
+ global __IAM_LOGGER
24
+ __IAM_LOGGER = logger
25
+
15
26
 
16
27
  # @flask_app.route(rule=<login_endpoint>, # JUSBR_ENDPOINT_LOGIN
17
28
  # methods=["GET"])
@@ -28,24 +39,22 @@ def service_login() -> Response:
28
39
  # declare the return variable
29
40
  result: Response | None = None
30
41
 
31
- # retrieve the operations's logger
32
- logger: Logger = _get_logger()
33
- if logger:
34
- # log the request
35
- logger.debug(msg=_log_init(request=request))
42
+ # log the request
43
+ if __IAM_LOGGER:
44
+ __IAM_LOGGER.debug(msg=_log_init(request=request))
36
45
 
37
46
  errors: list[str] = []
38
47
  with _iam_lock:
39
48
  # retrieve the IAM server
40
49
  iam_server: IamServer = _get_iam_server(endpoint=request.endpoint,
41
50
  errors=errors,
42
- logger=logger)
51
+ logger=__IAM_LOGGER)
43
52
  if iam_server:
44
53
  # obtain the login URL
45
54
  login_data: dict[str, str] = user_login(iam_server=iam_server,
46
55
  args=request.args,
47
56
  errors=errors,
48
- logger=logger)
57
+ logger=__IAM_LOGGER)
49
58
  if login_data:
50
59
  result = jsonify(login_data)
51
60
 
@@ -54,8 +63,8 @@ def service_login() -> Response:
54
63
  result.status_code = 400
55
64
 
56
65
  # log the response
57
- if logger:
58
- logger.debug(msg=f"Response {result}")
66
+ if __IAM_LOGGER:
67
+ __IAM_LOGGER.debug(msg=f"Response {result}")
59
68
 
60
69
  return result
61
70
 
@@ -75,24 +84,22 @@ def service_logout() -> Response:
75
84
  # declare the return variable
76
85
  result: Response | None
77
86
 
78
- # retrieve the operations's logger
79
- logger: Logger = _get_logger()
80
- if logger:
81
- # log the request
82
- logger.debug(msg=_log_init(request=request))
87
+ # log the request
88
+ if __IAM_LOGGER:
89
+ __IAM_LOGGER.debug(msg=_log_init(request=request))
83
90
 
84
91
  errors: list[str] = []
85
92
  with _iam_lock:
86
93
  # retrieve the IAM server
87
94
  iam_server: IamServer = _get_iam_server(endpoint=request.endpoint,
88
95
  errors=errors,
89
- logger=logger)
96
+ logger=__IAM_LOGGER)
90
97
  if iam_server:
91
98
  # logout the user
92
99
  user_logout(iam_server=iam_server,
93
100
  args=request.args,
94
101
  errors=errors,
95
- logger=logger)
102
+ logger=__IAM_LOGGER)
96
103
  if errors:
97
104
  result = Response("; ".join(errors))
98
105
  result.status_code = 400
@@ -100,8 +107,8 @@ def service_logout() -> Response:
100
107
  result = Response(status=204)
101
108
 
102
109
  # log the response
103
- if logger:
104
- logger.debug(msg=f"Response {result}")
110
+ if __IAM_LOGGER:
111
+ __IAM_LOGGER.debug(msg=f"Response {result}")
105
112
 
106
113
  return result
107
114
 
@@ -126,11 +133,9 @@ def service_callback() -> Response:
126
133
 
127
134
  :return: *Response* containing the reference user identification and the token, or *BAD REQUEST*
128
135
  """
129
- # retrieve the operations's logger
130
- logger: Logger = _get_logger()
131
- if logger:
132
- # log the request
133
- logger.debug(msg=_log_init(request=request))
136
+ # log the request
137
+ if __IAM_LOGGER:
138
+ __IAM_LOGGER.debug(msg=_log_init(request=request))
134
139
 
135
140
  errors: list[str] = []
136
141
  token_data: tuple[str, str] | None = None
@@ -138,25 +143,25 @@ def service_callback() -> Response:
138
143
  # retrieve the IAM server
139
144
  iam_server: IamServer = _get_iam_server(endpoint=request.endpoint,
140
145
  errors=errors,
141
- logger=logger)
146
+ logger=__IAM_LOGGER)
142
147
  if iam_server:
143
148
  # process the callback operation
144
149
  token_data = login_callback(iam_server=iam_server,
145
150
  args=request.args,
146
151
  errors=errors,
147
- logger=logger)
152
+ logger=__IAM_LOGGER)
148
153
  result: Response
149
154
  if errors:
150
155
  result = jsonify({"errors": "; ".join(errors)})
151
156
  result.status_code = 400
152
- if logger:
153
- logger.error(msg=json.dumps(obj=result))
157
+ if __IAM_LOGGER:
158
+ __IAM_LOGGER.error(msg=json.dumps(obj=result))
154
159
  else:
155
160
  result = jsonify({"user-id": token_data[0],
156
161
  "token": token_data[1]})
157
162
  # log the response
158
- if logger:
159
- logger.debug(msg=f"Response {result}")
163
+ if __IAM_LOGGER:
164
+ __IAM_LOGGER.debug(msg=f"Response {result}")
160
165
 
161
166
  return result
162
167
 
@@ -177,11 +182,9 @@ def service_token() -> Response:
177
182
 
178
183
  :return: *Response* containing the user reference identification and the token, or *BAD REQUEST*
179
184
  """
180
- # retrieve the operations's logger
181
- logger: Logger = _get_logger()
182
- if logger:
183
- # log the request
184
- logger.debug(msg=_log_init(request=request))
185
+ # log the request
186
+ if __IAM_LOGGER:
187
+ __IAM_LOGGER.debug(msg=_log_init(request=request))
185
188
 
186
189
  # obtain the user's identification
187
190
  args: dict[str, Any] = request.args
@@ -194,19 +197,19 @@ def service_token() -> Response:
194
197
  # retrieve the IAM server
195
198
  iam_server: IamServer = _get_iam_server(endpoint=request.endpoint,
196
199
  errors=errors,
197
- logger=logger)
200
+ logger=__IAM_LOGGER)
198
201
  if iam_server:
199
202
  # retrieve the token
200
203
  errors: list[str] = []
201
204
  token: str = user_token(iam_server=iam_server,
202
205
  args=args,
203
206
  errors=errors,
204
- logger=logger)
207
+ logger=__IAM_LOGGER)
205
208
  else:
206
209
  msg: str = "User identification not provided"
207
210
  errors.append(msg)
208
- if logger:
209
- logger.error(msg=msg)
211
+ if __IAM_LOGGER:
212
+ __IAM_LOGGER.error(msg=msg)
210
213
 
211
214
  result: Response
212
215
  if errors:
@@ -216,8 +219,8 @@ def service_token() -> Response:
216
219
  result = jsonify({"user-id": user_id,
217
220
  "token": token})
218
221
  # log the response
219
- if logger:
220
- logger.debug(msg=f"Response {result}")
222
+ if __IAM_LOGGER:
223
+ __IAM_LOGGER.debug(msg=f"Response {result}")
221
224
 
222
225
  return result
223
226
 
@@ -247,18 +250,16 @@ def service_exchange() -> Response:
247
250
 
248
251
  :return: *Response* containing the token data, or *BAD REQUEST*
249
252
  """
250
- # retrieve the operations's logger
251
- logger: Logger = _get_logger()
252
- if logger:
253
- # log the request
254
- logger.debug(msg=_log_init(request=request))
253
+ # log the request
254
+ if __IAM_LOGGER:
255
+ __IAM_LOGGER.debug(msg=_log_init(request=request))
255
256
 
256
257
  errors: list[str] = []
257
258
  with _iam_lock:
258
259
  # retrieve the IAM server (currently, only 'IAM_KEYCLOAK' is supported)
259
260
  iam_server: IamServer = _get_iam_server(endpoint=request.endpoint,
260
261
  errors=errors,
261
- logger=logger)
262
+ logger=__IAM_LOGGER)
262
263
  # exchange the token
263
264
  token_data: dict[str, Any] | None = None
264
265
  if iam_server:
@@ -266,7 +267,7 @@ def service_exchange() -> Response:
266
267
  token_data = token_exchange(iam_server=iam_server,
267
268
  args=request.args,
268
269
  errors=errors,
269
- logger=logger)
270
+ logger=__IAM_LOGGER)
270
271
  result: Response
271
272
  if errors:
272
273
  result = Response("; ".join(errors))
@@ -275,8 +276,8 @@ def service_exchange() -> Response:
275
276
  result = jsonify(token_data)
276
277
 
277
278
  # log the response
278
- if logger:
279
- logger.debug(msg=f"Response {result}")
279
+ if __IAM_LOGGER:
280
+ __IAM_LOGGER.debug(msg=f"Response {result}")
280
281
 
281
282
  return result
282
283
 
@@ -31,32 +31,32 @@ JUSBR_URL_AUTH_BASE: Final[str] = env_get_str(key=f"{APP_PREFIX}_JUSBR_URL_AUTH_
31
31
 
32
32
 
33
33
  def jusbr_setup(flask_app: Flask,
34
+ base_url: str = JUSBR_URL_AUTH_BASE,
34
35
  client_id: str = JUSBR_CLIENT_ID,
35
36
  client_secret: str = JUSBR_CLIENT_SECRET,
36
37
  client_timeout: int = JUSBR_CLIENT_TIMEOUT,
37
- public_key_lifetime: int = JUSBR_PUBLIC_KEY_LIFETIME,
38
- recipient_attribute: str = JUSBR_RECIPIENT_ATTR,
39
- callback_endpoint: str = JUSBR_ENDPOINT_CALLBACK,
40
- token_endpoint: str = JUSBR_ENDPOINT_TOKEN,
41
- login_endpoint: str = JUSBR_ENDPOINT_LOGIN,
42
- logout_endpoint: str = JUSBR_ENDPOINT_LOGOUT,
43
- base_url: str = JUSBR_URL_AUTH_BASE) -> None:
38
+ public_key_lifetime: int | None = JUSBR_PUBLIC_KEY_LIFETIME,
39
+ recipient_attribute: str | None = JUSBR_RECIPIENT_ATTR,
40
+ callback_endpoint: str | None = JUSBR_ENDPOINT_CALLBACK,
41
+ login_endpoint: str | None = JUSBR_ENDPOINT_LOGIN,
42
+ logout_endpoint: str | None = JUSBR_ENDPOINT_LOGOUT,
43
+ token_endpoint: str | None = JUSBR_ENDPOINT_TOKEN) -> None:
44
44
  """
45
45
  Configure the JusBR IAM.
46
46
 
47
47
  This should be invoked only once, before the first access to a JusBR service.
48
48
 
49
49
  :param flask_app: the Flask application
50
+ :param base_url: base URL to request JusBR services
50
51
  :param client_id: the client's identification with JusBR
51
52
  :param client_secret: the client's password with JusBR
52
53
  :param client_timeout: timeout for login authentication (in seconds,defaults to no timeout)
53
54
  :param public_key_lifetime: how long to use JusBR's public key, before refreshing it (in seconds)
54
55
  :param recipient_attribute: attribute in the token's payload holding the token's subject
55
56
  :param callback_endpoint: endpoint for the callback from JusBR
56
- :param token_endpoint: endpoint for retrieving JusBR's authentication token
57
57
  :param login_endpoint: endpoint for redirecting user to JusBR's login page
58
58
  :param logout_endpoint: endpoint for terminating user access to JusBR
59
- :param base_url: base URL to request JusBR services
59
+ :param token_endpoint: endpoint for retrieving JusBR's authentication token
60
60
  """
61
61
  from .iam_services import service_login, service_logout, service_callback, service_token
62
62
 
@@ -77,6 +77,11 @@ def jusbr_setup(flask_app: Flask,
77
77
  }
78
78
 
79
79
  # establish the endpoints
80
+ if callback_endpoint:
81
+ flask_app.add_url_rule(rule=callback_endpoint,
82
+ endpoint="jusbr-callback",
83
+ view_func=service_callback,
84
+ methods=["GET"])
80
85
  if login_endpoint:
81
86
  flask_app.add_url_rule(rule=login_endpoint,
82
87
  endpoint="jusbr-login",
@@ -87,11 +92,6 @@ def jusbr_setup(flask_app: Flask,
87
92
  endpoint="jusbr-logout",
88
93
  view_func=service_logout,
89
94
  methods=["GET"])
90
- if callback_endpoint:
91
- flask_app.add_url_rule(rule=callback_endpoint,
92
- endpoint="jusbr-callback",
93
- view_func=service_callback,
94
- methods=["GET"])
95
95
  if token_endpoint:
96
96
  flask_app.add_url_rule(rule=token_endpoint,
97
97
  endpoint="jusbr-token",
@@ -34,36 +34,36 @@ KEYCLOAK_URL_AUTH_BASE: Final[str] = env_get_str(key=f"{APP_PREFIX}_KEYCLOAK_URL
34
34
 
35
35
 
36
36
  def keycloak_setup(flask_app: Flask,
37
+ base_url: str = KEYCLOAK_URL_AUTH_BASE,
38
+ realm: str = KEYCLOAK_REALM,
37
39
  client_id: str = KEYCLOAK_CLIENT_ID,
38
40
  client_secret: str = KEYCLOAK_CLIENT_SECRET,
39
41
  client_timeout: int = KEYCLOAK_CLIENT_TIMEOUT,
40
- public_key_lifetime: int = KEYCLOAK_PUBLIC_KEY_LIFETIME,
41
- recipient_attribute: str = KEYCLOAK_RECIPIENT_ATTR,
42
- realm: str = KEYCLOAK_REALM,
43
- callback_endpoint: str = KEYCLOAK_ENDPOINT_CALLBACK,
44
- exchange_endpoint: str = KEYCLOAK_ENDPOINT_EXCHANGE,
45
- login_endpoint: str = KEYCLOAK_ENDPOINT_LOGIN,
46
- logout_endpoint: str = KEYCLOAK_ENDPOINT_LOGOUT,
47
- token_endpoint: str = KEYCLOAK_ENDPOINT_TOKEN,
48
- base_url: str = KEYCLOAK_URL_AUTH_BASE) -> None:
42
+ public_key_lifetime: int | None = KEYCLOAK_PUBLIC_KEY_LIFETIME,
43
+ recipient_attribute: str | None = KEYCLOAK_RECIPIENT_ATTR,
44
+ callback_endpoint: str | None = KEYCLOAK_ENDPOINT_CALLBACK,
45
+ login_endpoint: str | None = KEYCLOAK_ENDPOINT_LOGIN,
46
+ logout_endpoint: str | None = KEYCLOAK_ENDPOINT_LOGOUT,
47
+ token_endpoint: str | None = KEYCLOAK_ENDPOINT_TOKEN,
48
+ exchange_endpoint: str | None = KEYCLOAK_ENDPOINT_EXCHANGE) -> None:
49
49
  """
50
50
  Configure the Keycloak IAM.
51
51
 
52
52
  This should be invoked only once, before the first access to a Keycloak service.
53
53
 
54
54
  :param flask_app: the Flask application
55
+ :param base_url: base URL to request Keycloak services
56
+ :param realm: the Keycloak realm
55
57
  :param client_id: the client's identification with JusBR
56
58
  :param client_secret: the client's password with JusBR
57
59
  :param client_timeout: timeout for login authentication (in seconds,defaults to no timeout)
58
60
  :param public_key_lifetime: how long to use Keycloak's public key, before refreshing it (in seconds)
59
61
  :param recipient_attribute: attribute in the token's payload holding the token's subject
60
- :param realm: the Keycloak realm
61
62
  :param callback_endpoint: endpoint for the callback from the front end
62
- :param exchange_endpoint: endpoint fro requesting token exchange
63
- :param token_endpoint: endpoint for retrieving Keycloak's authentication token
64
63
  :param login_endpoint: endpoint for redirecting user to Keycloak's login page
65
64
  :param logout_endpoint: endpoint for terminating user access to Keycloak
66
- :param base_url: base URL to request Keycloak services
65
+ :param token_endpoint: endpoint for retrieving Keycloak's authentication token
66
+ :param exchange_endpoint: endpoint for requesting token exchange
67
67
  """
68
68
  from .iam_services import (
69
69
  service_login, service_logout, service_callback, service_exchange, service_token
@@ -86,6 +86,11 @@ def keycloak_setup(flask_app: Flask,
86
86
  }
87
87
 
88
88
  # establish the endpoints
89
+ if callback_endpoint:
90
+ flask_app.add_url_rule(rule=callback_endpoint,
91
+ endpoint="keycloak-callback",
92
+ view_func=service_callback,
93
+ methods=["GET"])
89
94
  if login_endpoint:
90
95
  flask_app.add_url_rule(rule=login_endpoint,
91
96
  endpoint="keycloak-login",
@@ -96,11 +101,6 @@ def keycloak_setup(flask_app: Flask,
96
101
  endpoint="keycloak-logout",
97
102
  view_func=service_logout,
98
103
  methods=["GET"])
99
- if callback_endpoint:
100
- flask_app.add_url_rule(rule=callback_endpoint,
101
- endpoint="keycloak-callback",
102
- view_func=service_callback,
103
- methods=["GET"])
104
104
  if token_endpoint:
105
105
  flask_app.add_url_rule(rule=token_endpoint,
106
106
  endpoint="keycloak-token",
File without changes
File without changes
File without changes