Files
deb-murano/murano/api/middleware/ext_context.py
Gyorgy Szombathelyi 3d20f25d3b Use keystoneauth1 lib for authentication helpers
If auth_type is set in the keystone_authtoken section,
then one can use the the keystoneauth1 library to load the
authentication plugin. This makes muranoclient fully workable,
with Keystone v3 in case domain name is not 'Default'.

Related-Bug: 1580611

Change-Id: I0d71032fb5296752ee25482b75993072884731e7
2016-07-08 12:46:17 +00:00

112 lines
4.1 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.
import base64
from keystoneauth1 import exceptions
from keystoneauth1.identity import v3
from keystoneauth1 import session as ks_session
from oslo_config import cfg
from oslo_log import log
from webob import exc
from murano.common.i18n import _, _LW
from murano.common import wsgi
CONF = cfg.CONF
LOG = log.getLogger(__name__)
class ExternalContextMiddleware(wsgi.Middleware):
def get_keystone_token(self, user, password):
# TODO(starodubcevna): picking up project_name and auth_url from
# section related to Cloud Foundry service broker is probably a duct
# tape and should be rewritten as soon as we get more non-OpenStack
# services as murano recipients. The same is right for project and user
# domain names.
auth_url = CONF.cfapi.auth_url
if not (auth_url.endswith('v2.0') or auth_url.endswith('v3')):
auth_url += '/v3'
elif auth_url.endswith('v2.0'):
auth_url = auth_url.replace('v2.0', 'v3')
elif auth_url.endswith('v3'):
pass
else:
LOG.warning(_LW('Wrong format for service broker auth url'))
kwargs = {'auth_url': auth_url,
'username': user,
'password': password,
'project_name': CONF.cfapi.tenant,
'user_domain_name': CONF.cfapi.user_domain_name,
'project_domain_name': CONF.cfapi.project_domain_name}
password_auth = v3.Password(**kwargs)
session = ks_session.Session(auth=password_auth)
self._query_endpoints(password_auth, session)
return session.get_token()
def _query_endpoints(self, auth, session):
if not hasattr(self, '_murano_endpoint'):
try:
self._murano_endpoint = auth.get_endpoint(
session, 'application-catalog')
except exceptions.EndpointNotFound:
pass
if not hasattr(self, '_glare_endpoint'):
try:
self._glare_endpoint = auth.get_endpoint(
session, 'artifact')
except exceptions.EndpointNotFound:
pass
def get_endpoints(self):
return {
'murano': getattr(self, '_murano_endpoint', None),
'glare': getattr(self, '_glare_endpoint', None),
}
def process_request(self, req):
"""Get keystone token for external request
This middleware is used for external requests. It get credentials from
request and try to get keystone token for further authorization.
:param req: wsgi request object that will be given the context object
"""
try:
credentials = base64.b64decode(
req.headers['Authorization'].split(' ')[1])
user, password = credentials.split(':', 2)
req.headers['X-Auth-Token'] = self.get_keystone_token(user,
password)
req.endpoints = self.get_endpoints()
except KeyError:
msg = _("Authorization required")
LOG.warning(msg)
raise exc.HTTPUnauthorized(explanation=msg)
except exceptions.Unauthorized:
msg = _("Your credentials are wrong. Please try again")
LOG.warning(msg)
raise exc.HTTPUnauthorized(explanation=msg)
@classmethod
def factory(cls, global_conf, **local_conf):
def filter(app):
return cls(app)
return filter