Fix getting token from application credentials token
When user tries to get token from token that was initially issued using application credentials it is necessary to restore the initial application credential is to enforce it's scope, roles and access rules. Closes-bug: #2111836 Change-Id: Ie94f7e18106b50087284bd8c81b50aa50ab104cb Signed-off-by: Artem Goncharov <artem.goncharov@gmail.com>
This commit is contained in:
@@ -178,6 +178,13 @@ def authenticate(auth_info, auth_context):
|
||||
resp_method_names = resp.response_data.pop('method_names', [])
|
||||
auth_context['method_names'].extend(resp_method_names)
|
||||
auth_context.update(resp.response_data or {})
|
||||
# NOTE(gtema): When trying to get token from
|
||||
# application_credential based token we need to restore
|
||||
# application_credential_id to prevent escaping its bounds.
|
||||
if "application_credential_id" in resp:
|
||||
auth_context["application_credential_id"] = resp[
|
||||
"application_credential_id"
|
||||
]
|
||||
elif resp.response_body:
|
||||
auth_response['methods'].append(method_name)
|
||||
auth_response[method_name] = resp.response_body
|
||||
@@ -226,7 +233,14 @@ def authenticate_for_token(auth=None):
|
||||
app_cred_id = None
|
||||
if 'application_credential' in method_names:
|
||||
token_auth = auth_info.auth['identity']
|
||||
app_cred_id = token_auth['application_credential']['id']
|
||||
if "application_credential" in token_auth:
|
||||
app_cred_id = token_auth['application_credential']['id']
|
||||
elif "application_credential_id" in auth_context:
|
||||
app_cred_id = auth_context["application_credential_id"]
|
||||
else:
|
||||
raise exception.MissingApplicationCredentialId(
|
||||
user_id=auth_context['user_id']
|
||||
)
|
||||
|
||||
# Do MFA Rule Validation for the user
|
||||
if not core.UserMFARulesValidator.check_auth_methods_against_rules(
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
import flask
|
||||
from oslo_log import log
|
||||
import typing as ty
|
||||
|
||||
from keystone.auth.plugins import base
|
||||
from keystone.auth.plugins import mapped
|
||||
@@ -21,6 +22,7 @@ from keystone.common import provider_api
|
||||
import keystone.conf
|
||||
from keystone import exception
|
||||
from keystone.i18n import _
|
||||
from keystone.models.token_model import TokenModel
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
@@ -49,13 +51,12 @@ class Token(base.AuthMethodHandler):
|
||||
# for re-scoping and we want to maintain the values. Most
|
||||
# AuthMethodHandlers do no such thing and this is not required.
|
||||
response_data.setdefault('method_names', []).extend(token.methods)
|
||||
|
||||
return base.AuthHandlerResponse(
|
||||
status=True, response_body=None, response_data=response_data
|
||||
)
|
||||
|
||||
|
||||
def token_authenticate(token):
|
||||
def token_authenticate(token: TokenModel) -> dict[str, ty.Any]:
|
||||
response_data = {}
|
||||
try:
|
||||
# Do not allow tokens used for delegation to
|
||||
@@ -88,6 +89,20 @@ def token_authenticate(token):
|
||||
'or domain-scoped token is not allowed.'
|
||||
)
|
||||
)
|
||||
elif token.application_credential:
|
||||
# NOTE(gtema): when getting token from token (initially issued by
|
||||
# application credential) it is necessary to ensure scope is not
|
||||
# requested.
|
||||
if project_scoped or domain_scoped:
|
||||
raise exception.ForbiddenAction(
|
||||
action=_(
|
||||
"Using an application credential token to create a "
|
||||
"project-scoped or domain-scoped token is not allowed."
|
||||
)
|
||||
)
|
||||
response_data["application_credential_id"] = (
|
||||
token.application_credential["id"]
|
||||
)
|
||||
|
||||
if not CONF.token.allow_rescope_scoped_token:
|
||||
# Do not allow conversion from scoped tokens.
|
||||
|
||||
Reference in New Issue
Block a user