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/__init__.py +20 -8
- pypomes_iam/iam_actions.py +878 -0
- pypomes_iam/iam_common.py +388 -0
- pypomes_iam/iam_pomes.py +137 -157
- pypomes_iam/iam_services.py +394 -0
- pypomes_iam/provider_pomes.py +175 -72
- pypomes_iam/token_pomes.py +63 -8
- {pypomes_iam-0.2.3.dist-info → pypomes_iam-0.7.0.dist-info}/METADATA +1 -2
- pypomes_iam-0.7.0.dist-info/RECORD +11 -0
- pypomes_iam/common_pomes.py +0 -397
- pypomes_iam/jusbr_pomes.py +0 -167
- pypomes_iam/keycloak_pomes.py +0 -170
- pypomes_iam-0.2.3.dist-info/RECORD +0 -11
- {pypomes_iam-0.2.3.dist-info → pypomes_iam-0.7.0.dist-info}/WHEEL +0 -0
- {pypomes_iam-0.2.3.dist-info → pypomes_iam-0.7.0.dist-info}/licenses/LICENSE +0 -0
pypomes_iam/iam_pomes.py
CHANGED
|
@@ -1,176 +1,156 @@
|
|
|
1
|
-
from flask import
|
|
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 .
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
92
|
-
|
|
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
|
-
|
|
98
|
-
|
|
99
|
-
|
|
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
|
-
|
|
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
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
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
|
-
|
|
147
|
-
|
|
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
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
|