Merge "Fix getting token from application credentials token" into stable/2025.1

This commit is contained in:
Zuul
2025-12-16 09:50:40 +00:00
committed by Gerrit Code Review
2 changed files with 32 additions and 3 deletions

View File

@@ -183,6 +183,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
@@ -231,7 +238,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(

View File

@@ -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.