pypomes-iam 0.2.3__py3-none-any.whl → 0.7.0__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.

Potentially problematic release.


This version of pypomes-iam might be problematic. Click here for more details.

pypomes_iam/iam_pomes.py CHANGED
@@ -1,176 +1,156 @@
1
- from flask import Response, redirect, request, jsonify
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
- from .common_pomes import (
6
- _service_login, _service_logout,
7
- _service_callback, _service_token, _log_init
6
+ from .iam_common import (
7
+ _IAM_SERVERS, IamServer, IamParam, _iam_lock
8
+ )
9
+ from .iam_actions import action_token
10
+ from .iam_services import (
11
+ service_login, service_logout, service_callback, service_exchange, service_token
8
12
  )
9
- from .jusbr_pomes import _jusbr_get_logger, _jusbr_get_registry
10
- from .keycloak_pomes import _keycloak_get_logger, _keycloak_get_registry
11
13
 
12
14
 
13
- # @flask_app.route(rule=<login_endpoint>, # JUSBR_LOGIN_ENDPOINT: /iam/jusbr:login
14
- # methods=["GET"])
15
- # @flask_app.route(rule=<login_endpoint>, # KEYCLOAK_LOGIN_ENDPOINT: /iam/keycloak:logout
16
- # methods=["GET"])
17
- def service_login() -> Response:
15
+ def iam_setup(flask_app: Flask,
16
+ iam_server: IamServer,
17
+ base_url: str,
18
+ client_id: str,
19
+ client_realm: str,
20
+ client_secret: str | None,
21
+ recipient_attribute: str,
22
+ admin_id: str = None,
23
+ admin_secret: str = None,
24
+ login_timeout: int = None,
25
+ public_key_lifetime: int = None,
26
+ callback_endpoint: str = None,
27
+ exchange_endpoint: str = None,
28
+ login_endpoint: str = None,
29
+ logout_endpoint: str = None,
30
+ token_endpoint: str = None) -> None:
18
31
  """
19
- Entry point for the JusBR login service.
20
-
21
- Redirect the request to the JusBR authentication page, with the appropriate parameters.
22
-
23
- :return: the response from the redirect operation
32
+ Establish the provided parameters for configuring the *IAM* server *iam_server*.
33
+
34
+ The parameters *admin_id* and *admin_* are required only if administrative are task are planned.
35
+ The optional parameter *client_timeout* refers to the maximum time in seconds allowed for the
36
+ user to login at the *IAM* server's login page, and defaults to no time limit.
37
+
38
+ The parameter *client_secret* is required in most requests to the *IAM* server. In the case
39
+ it is not provided, but *admin_id* and *admin_secret* are, it is obtained from the *IAM* server itself
40
+ the first time it is needed.
41
+
42
+ :param flask_app: the Flask application
43
+ :param iam_server: identifies the supported *IAM* server (currently, *jusbr* or *keycloak*)
44
+ :param base_url: base URL to request services
45
+ :param client_id: the client's identification with the *IAM* server
46
+ :param client_realm: the client realm
47
+ :param client_secret: the client's password with the *IAM* server
48
+ :param recipient_attribute: attribute in the token's payload holding the token's subject
49
+ :param admin_id: identifies the realm administrator
50
+ :param admin_secret: password for the realm administrator
51
+ :param login_timeout: timeout for login authentication (in seconds,defaults to no timeout)
52
+ :param public_key_lifetime: how long to use *IAM* server's public key, before refreshing it (in seconds)
53
+ :param callback_endpoint: endpoint for the callback from the front end
54
+ :param exchange_endpoint: endpoint for requesting token exchange
55
+ :param login_endpoint: endpoint for redirecting user to the *IAM* server's login page
56
+ :param logout_endpoint: endpoint for terminating user access
57
+ :param token_endpoint: endpoint for retrieving authentication token
24
58
  """
25
- logger: Logger
26
- registry: dict[str, Any]
27
- if request.endpoint == "jusbr-login":
28
- logger = _jusbr_get_logger()
29
- registry = _jusbr_get_registry()
30
- else:
31
- logger = _keycloak_get_logger()
32
- registry = _keycloak_get_registry()
33
-
34
- # log the request
35
- if logger:
36
- logger.debug(msg=_log_init(request=request))
37
-
38
- # obtain the redirect URL
39
- auth_url: str = _service_login(registry=registry,
40
- args=request.args,
41
- logger=logger)
42
- # redirect the request
43
- result: Response = redirect(location=auth_url)
44
-
45
- # log the response
46
- if logger:
47
- logger.debug(msg=f"Response {result}")
48
-
49
- return result
50
-
51
-
52
- # @flask_app.route(rule=<logout_endpoint>, # JUSBR_LOGOUT_ENDPOINT: /iam/jusbr:logout
53
- # methods=["GET"])
54
- # @flask_app.route(rule=<login_endpoint>, # KEYCLOAK_LOGOUT_ENDPOINT: /iam/keycloak:logout
55
- # methods=["GET"])
56
- def service_logout() -> Response:
57
- """
58
- Entry point for the JusBR logout service.
59
-
60
- Remove all data associating the user with JusBR from the registry.
61
59
 
62
- :return: response *OK*
60
+ # configure the Keycloak registry
61
+ with _iam_lock:
62
+ _IAM_SERVERS[iam_server] = {
63
+ IamParam.URL_BASE: base_url,
64
+ IamParam.CLIENT_ID: client_id,
65
+ IamParam.CLIENT_REALM: client_realm,
66
+ IamParam.CLIENT_SECRET: client_secret,
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,
72
+ IamParam.PK_EXPIRATION: 0,
73
+ IamParam.PUBLIC_KEY: None,
74
+ IamParam.USERS: {}
75
+ }
76
+
77
+ # establish the endpoints
78
+ if callback_endpoint:
79
+ flask_app.add_url_rule(rule=callback_endpoint,
80
+ endpoint=f"{iam_server}-callback",
81
+ view_func=service_callback,
82
+ methods=["GET"])
83
+ if login_endpoint:
84
+ flask_app.add_url_rule(rule=login_endpoint,
85
+ endpoint=f"{iam_server}-login",
86
+ view_func=service_login,
87
+ methods=["GET"])
88
+ if logout_endpoint:
89
+ flask_app.add_url_rule(rule=logout_endpoint,
90
+ endpoint=f"{iam_server}-logout",
91
+ view_func=service_logout,
92
+ methods=["GET"])
93
+ if token_endpoint:
94
+ flask_app.add_url_rule(rule=token_endpoint,
95
+ endpoint=f"{iam_server}-token",
96
+ view_func=service_token,
97
+ methods=["GET"])
98
+ if exchange_endpoint:
99
+ flask_app.add_url_rule(rule=exchange_endpoint,
100
+ endpoint=f"{iam_server}-exchange",
101
+ view_func=service_exchange,
102
+ methods=["POST"])
103
+
104
+
105
+ def iam_get_env_parameters(iam_prefix: str = None) -> dict[str, Any]:
63
106
  """
64
- logger: Logger
65
- registry: dict[str, Any]
66
- if request.endpoint == "jusbr-logout":
67
- logger = _jusbr_get_logger()
68
- registry = _jusbr_get_registry()
69
- else:
70
- logger = _keycloak_get_logger()
71
- registry = _keycloak_get_registry()
72
-
73
- # log the request
74
- if logger:
75
- logger.debug(msg=_log_init(request=request))
76
-
77
- # logout the user
78
- _service_logout(registry=registry,
79
- args=request.args,
80
- logger=logger)
81
-
82
- result: Response = Response(status=200)
83
-
84
- # log the response
85
- if logger:
86
- logger.debug(msg=f"Response {result}")
87
-
88
- return result
107
+ Retrieve the set parameters for a *IAM* server from the environment.
89
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.
90
111
 
91
- # @flask_app.route(rule=<callback_endpoint>, # JUSBR_CALLBACK_ENDPOINT: /iam/jusbr:callback
92
- # methods=["GET", "POST"])
93
- # @flask_app.route(rule=<callback_endpoint>, # KEYCLOAK_CALLBACK_ENDPOINT: /iam/keycloak:callback
94
- # methods=["POST"])
95
- def service_callback() -> Response:
112
+ :param iam_prefix: the prefix classifying the parameters
113
+ :return: the sorted parameters classified by *prefix*
96
114
  """
97
- Entry point for the callback from JusBR on authentication operation.
98
-
99
- :return: the response containing the token, or *BAD REQUEST*
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
+
133
+ def iam_get_token(iam_server: IamServer,
134
+ user_id: str,
135
+ errors: list[str] = None,
136
+ logger: Logger = None) -> str:
100
137
  """
101
- logger: Logger
102
- registry: dict[str, Any]
103
- if request.endpoint == "jusbr-callback":
104
- logger = _jusbr_get_logger()
105
- registry = _jusbr_get_registry()
106
- else:
107
- logger = _keycloak_get_logger()
108
- registry = _keycloak_get_registry()
109
-
110
- # log the request
111
- if logger:
112
- logger.debug(msg=_log_init(request=request))
113
-
114
- # process the callback operation
115
- errors: list[str] = []
116
- token_data: tuple[str, str] = _service_callback(registry=registry,
117
- args=request.args,
118
- errors=errors,
119
- logger=logger)
120
- result: Response
121
- if errors:
122
- result = jsonify({"errors": "; ".join(errors)})
123
- result.status_code = 400
124
- else:
125
- result = jsonify({
126
- "user_id": token_data[0],
127
- "access_token": token_data[1]})
128
-
129
- # log the response
130
- if logger:
131
- logger.debug(msg=f"Response {result}")
132
-
133
- return result
138
+ Retrieve an authentication token for *user_id*.
134
139
 
135
-
136
- # @flask_app.route(rule=<token_endpoint>, # JUSBR_TOKEN_ENDPOINT: /iam/jusbr:get-token
137
- # methods=["GET"])
138
- # @flask_app.route(rule=<token_endpoint>, # JUSBR_TOKEN_ENDPOINT: /iam/jusbr:get-token
139
- # methods=["GET"])
140
- def service_token() -> Response:
141
- """
142
- Entry point for retrieving the JusBR token.
143
-
144
- :return: the response containing the token, or *UNAUTHORIZED*
140
+ :param iam_server: identifies the *IAM* server
141
+ :param user_id: identifies the user
142
+ :param errors: incidental errors
143
+ :param logger: optional logger
144
+ :return: the uthentication tokem
145
145
  """
146
- logger: Logger
147
- registry: dict[str, Any]
148
- if request.endpoint == "jusbr-token":
149
- logger = _jusbr_get_logger()
150
- registry = _jusbr_get_registry()
151
- else:
152
- logger = _keycloak_get_logger()
153
- registry = _keycloak_get_registry()
154
-
155
- # log the request
156
- if logger:
157
- logger.debug(msg=_log_init(request=request))
146
+ # declare the return variable
147
+ result: str
158
148
 
159
149
  # retrieve the token
160
- errors: list[str] = []
161
- token: str = _service_token(registry=registry,
162
- args=request.args,
163
- errors=errors,
164
- logger=logger)
165
- result: Response
166
- if token:
167
- result = jsonify({"token": token})
168
- else:
169
- result = Response("; ".join(errors))
170
- result.status_code = 401
171
-
172
- # log the response
173
- if logger:
174
- logger.debug(msg=f"Response {result}")
175
-
150
+ args: dict[str, Any] = {"user-id": user_id}
151
+ with _iam_lock:
152
+ result = action_token(iam_server=iam_server,
153
+ args=args,
154
+ errors=errors,
155
+ logger=logger)
176
156
  return result