glance/glance/common/trust_auth.py
Erno Kuvaja 9b683678b2 Revert "Remove all usage of keystoneclient"
This reverts commit 810417df86.

The Swift driver not being able to use Trusts had nothing to do
about the store driver itself nor that keystoneauth1 would have
broken the feature, but rather it not having the functionality
in the first place and us not catching that on reviews.

We should figure out how to test this before we try to replace
this code again.

Change-Id: If12a013404296486dc387b099477d1608b24ba63
Closes-Bug: #1916052
2021-06-10 13:51:49 +01:00

110 lines
4.4 KiB
Python

# Copyright (c) 2015 Mirantis, Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from keystoneauth1 import exceptions as ka_exceptions
from keystoneauth1 import loading as ka_loading
from keystoneclient.v3 import client as ks_client
from oslo_config import cfg
from oslo_log import log as logging
CONF = cfg.CONF
CONF.register_opt(cfg.IntOpt('timeout'), group='keystone_authtoken')
LOG = logging.getLogger(__name__)
class TokenRefresher(object):
"""Class that responsible for token refreshing with trusts"""
def __init__(self, user_plugin, user_project, user_roles):
"""Prepare all parameters and clients required to refresh token"""
# step 1: create trust to ensure that we can always update token
# trustor = user who made the request
trustor_client = self._load_client(user_plugin)
trustor_id = trustor_client.session.get_user_id()
# get trustee user client that impersonates main user
trustee_user_auth = ka_loading.load_auth_from_conf_options(
CONF, 'keystone_authtoken')
# save service user client because we need new service token
# to refresh trust-scoped client later
self.trustee_user_client = self._load_client(trustee_user_auth)
trustee_id = self.trustee_user_client.session.get_user_id()
self.trust_id = trustor_client.trusts.create(trustor_user=trustor_id,
trustee_user=trustee_id,
impersonation=True,
role_names=user_roles,
project=user_project).id
LOG.debug("Trust %s has been created.", self.trust_id)
# step 2: postpone trust-scoped client initialization
# until we need to refresh the token
self.trustee_client = None
def refresh_token(self):
"""Receive new token if user need to update old token
:return: new token that can be used for authentication
"""
LOG.debug("Requesting the new token with trust %s", self.trust_id)
if self.trustee_client is None:
self.trustee_client = self._refresh_trustee_client()
try:
return self.trustee_client.session.get_token()
except ka_exceptions.Unauthorized:
# in case of Unauthorized exceptions try to refresh client because
# service user token may expired
self.trustee_client = self._refresh_trustee_client()
return self.trustee_client.session.get_token()
def release_resources(self):
"""Release keystone resources required for refreshing"""
try:
if self.trustee_client is None:
self._refresh_trustee_client().trusts.delete(self.trust_id)
else:
self.trustee_client.trusts.delete(self.trust_id)
except ka_exceptions.Unauthorized:
# service user token may expire when we are trying to delete token
# so need to update client to ensure that this is not the reason
# of failure
self.trustee_client = self._refresh_trustee_client()
self.trustee_client.trusts.delete(self.trust_id)
def _refresh_trustee_client(self):
# Remove project_name and project_id, since we need a trust scoped
# auth object
kwargs = {
'project_name': None,
'project_domain_name': None,
'project_id': None,
'trust_id': self.trust_id
}
trustee_auth = ka_loading.load_auth_from_conf_options(
CONF, 'keystone_authtoken', **kwargs)
return self._load_client(trustee_auth)
@staticmethod
def _load_client(plugin):
# load client from auth settings and user plugin
sess = ka_loading.load_session_from_conf_options(
CONF, 'keystone_authtoken', auth=plugin)
return ks_client.Client(session=sess)