Split up extracting auth.py file
The auth.py file does a couple of things, It contains keystone authentication and to set request context. So this split up to two files. After this commit, request hook should be included in hooks.py. Related-Bug: #1406539 Change-Id: I1754da40383976e48f6fd4ca23911717f918f9bb
This commit is contained in:
parent
a6f4f0f137
commit
c6c606b277
@ -54,4 +54,5 @@ def setup_app(config=None):
|
|||||||
logging=getattr(config, 'logging', {}),
|
logging=getattr(config, 'logging', {}),
|
||||||
**app_conf
|
**app_conf
|
||||||
)
|
)
|
||||||
return auth.install(app, CONF)
|
|
||||||
|
return auth.install(app, CONF, config.app.acl_public_routes)
|
||||||
|
@ -1,5 +1,8 @@
|
|||||||
# -*- encoding: utf-8 -*-
|
# -*- encoding: utf-8 -*-
|
||||||
#
|
#
|
||||||
|
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||||
|
#
|
||||||
|
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
|
||||||
#
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License"); you may
|
# 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
|
# not use this file except in compliance with the License. You may obtain
|
||||||
@ -13,22 +16,12 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import re
|
"""Access Control Lists (ACL's) control access the API server."""
|
||||||
|
|
||||||
from keystonemiddleware import auth_token
|
|
||||||
from oslo.config import cfg
|
from oslo.config import cfg
|
||||||
from oslo.utils import importutils
|
|
||||||
from pecan import hooks
|
|
||||||
|
|
||||||
from magnum.common import context
|
from magnum.api.middleware import auth_token
|
||||||
from magnum.openstack.common._i18n import _
|
|
||||||
from magnum.openstack.common import log as logging
|
|
||||||
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
|
||||||
|
|
||||||
OPT_GROUP_NAME = 'keystone_authtoken'
|
|
||||||
|
|
||||||
AUTH_OPTS = [
|
AUTH_OPTS = [
|
||||||
cfg.BoolOpt('enable_authentication',
|
cfg.BoolOpt('enable_authentication',
|
||||||
default=True,
|
default=True,
|
||||||
@ -39,99 +32,19 @@ AUTH_OPTS = [
|
|||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
CONF.register_opts(AUTH_OPTS)
|
CONF.register_opts(AUTH_OPTS)
|
||||||
|
|
||||||
PUBLIC_ENDPOINTS = [
|
|
||||||
"^/$"
|
|
||||||
]
|
|
||||||
|
|
||||||
|
def install(app, conf, public_routes):
|
||||||
|
"""Install ACL check on application.
|
||||||
|
|
||||||
def install(app, conf):
|
:param app: A WSGI applicatin.
|
||||||
if conf.get('enable_authentication'):
|
:param conf: Settings. Dict'ified and passed to keystonemiddleware
|
||||||
return AuthProtocolWrapper(app, conf=dict(conf.get(OPT_GROUP_NAME)))
|
:param public_routes: The list of the routes which will be allowed to
|
||||||
else:
|
access without authentication.
|
||||||
LOG.warning(_('Keystone authentication is disabled by Magnum '
|
:return: The same WSGI application with ACL installed.
|
||||||
'configuration parameter enable_authentication. '
|
|
||||||
'Magnum will not authenticate incoming request. '
|
|
||||||
'In order to enable authentication set '
|
|
||||||
'enable_authentication option to True.'))
|
|
||||||
|
|
||||||
return app
|
|
||||||
|
|
||||||
|
|
||||||
class AuthHelper(object):
|
|
||||||
"""Helper methods for Auth."""
|
|
||||||
|
|
||||||
def __init__(self):
|
|
||||||
endpoints_pattern = '|'.join(pe for pe in PUBLIC_ENDPOINTS)
|
|
||||||
self._public_endpoints_regexp = re.compile(endpoints_pattern)
|
|
||||||
|
|
||||||
def is_endpoint_public(self, path):
|
|
||||||
return self._public_endpoints_regexp.match(path)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthProtocolWrapper(auth_token.AuthProtocol):
|
|
||||||
"""A wrapper on Keystone auth_token AuthProtocol.
|
|
||||||
|
|
||||||
Does not perform verification of authentication tokens for pub routes in
|
|
||||||
the API. Public routes are those defined by PUBLIC_ENDPOINTS
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
if not cfg.CONF.get('enable_authentication'):
|
||||||
def __call__(self, env, start_response):
|
return app
|
||||||
path = env.get('PATH_INFO')
|
return auth_token.AuthTokenMiddleware(app,
|
||||||
if AUTH.is_endpoint_public(path):
|
conf=dict(conf),
|
||||||
return self._app(env, start_response)
|
public_api_routes=public_routes)
|
||||||
return super(AuthProtocolWrapper, self).__call__(env, start_response)
|
|
||||||
|
|
||||||
|
|
||||||
class AuthInformationHook(hooks.PecanHook):
|
|
||||||
|
|
||||||
def before(self, state):
|
|
||||||
if not CONF.get('enable_authentication'):
|
|
||||||
return
|
|
||||||
# Skip authentication for public endpoints
|
|
||||||
if AUTH.is_endpoint_public(state.request.path):
|
|
||||||
return
|
|
||||||
|
|
||||||
headers = state.request.headers
|
|
||||||
user_id = headers.get('X-User-Id')
|
|
||||||
user_id = headers.get('X-User', user_id)
|
|
||||||
if user_id is None:
|
|
||||||
LOG.debug("X-User-Id header was not found in the request")
|
|
||||||
raise Exception('Not authorized')
|
|
||||||
|
|
||||||
tenant = state.request.headers.get('X-Tenant-Id')
|
|
||||||
tenant = state.request.headers.get('X-Tenant', tenant)
|
|
||||||
domain_id = state.request.headers.get('X-User-Domain-Id')
|
|
||||||
domain_name = state.request.headers.get('X-User-Domain-Name')
|
|
||||||
auth_token_info = state.request.environ.get('keystone.token_info')
|
|
||||||
|
|
||||||
# Get the auth token
|
|
||||||
try:
|
|
||||||
recv_auth_token = headers.get('X-Auth-Token',
|
|
||||||
headers.get(
|
|
||||||
'X-Storage-Token'))
|
|
||||||
except ValueError:
|
|
||||||
LOG.debug("No auth token found in the request.")
|
|
||||||
raise Exception('Not authorized')
|
|
||||||
auth_url = headers.get('X-Auth-Url')
|
|
||||||
if auth_url is None:
|
|
||||||
importutils.import_module('keystonemiddleware.auth_token')
|
|
||||||
auth_url = cfg.CONF.keystone_authtoken.auth_uri
|
|
||||||
|
|
||||||
identity_status = headers.get('X-Identity-Status')
|
|
||||||
if identity_status == 'Confirmed':
|
|
||||||
ctx = context.RequestContext(auth_token=recv_auth_token,
|
|
||||||
auth_url=auth_url,
|
|
||||||
auth_token_info=auth_token_info,
|
|
||||||
user=user_id,
|
|
||||||
tenant=tenant,
|
|
||||||
domain_id=domain_id,
|
|
||||||
domain_name=domain_name)
|
|
||||||
state.request.context = ctx
|
|
||||||
else:
|
|
||||||
LOG.debug("The provided identity is not confirmed.")
|
|
||||||
raise Exception('Not authorized. Identity not confirmed.')
|
|
||||||
return
|
|
||||||
|
|
||||||
|
|
||||||
AUTH = AuthHelper()
|
|
||||||
|
@ -14,14 +14,19 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from magnum.api import auth
|
from magnum.api import hooks
|
||||||
|
|
||||||
# Pecan Application Configurations
|
# Pecan Application Configurations
|
||||||
app = {
|
app = {
|
||||||
'root': 'magnum.api.controllers.root.RootController',
|
'root': 'magnum.api.controllers.root.RootController',
|
||||||
'modules': ['magnum.api'],
|
'modules': ['magnum.api'],
|
||||||
'debug': False,
|
'debug': False,
|
||||||
'hooks': [auth.AuthInformationHook()]
|
'hooks': [
|
||||||
|
hooks.ContextHook()
|
||||||
|
],
|
||||||
|
'acl_public_routes': [
|
||||||
|
'/'
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Custom Configurations must be in Python dictionary format::
|
# Custom Configurations must be in Python dictionary format::
|
||||||
|
67
magnum/api/hooks.py
Normal file
67
magnum/api/hooks.py
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# Copyright © 2012 New Dream Network, LLC (DreamHost)
|
||||||
|
#
|
||||||
|
# Author: Doug Hellmann <doug.hellmann@dreamhost.com>
|
||||||
|
#
|
||||||
|
# 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 oslo.config import cfg
|
||||||
|
from oslo.utils import importutils
|
||||||
|
from pecan import hooks
|
||||||
|
|
||||||
|
from magnum.common import context
|
||||||
|
|
||||||
|
|
||||||
|
class ContextHook(hooks.PecanHook):
|
||||||
|
"""Configures a request context and attaches it to the request.
|
||||||
|
|
||||||
|
The following HTTP request headers are used:
|
||||||
|
|
||||||
|
X-User-Id or X-User:
|
||||||
|
Used for context.user_id.
|
||||||
|
|
||||||
|
X-Tenant-Id or X-Tenant:
|
||||||
|
Used for context.tenant.
|
||||||
|
|
||||||
|
X-Auth-Token:
|
||||||
|
Used for context.auth_token.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
def before(self, state):
|
||||||
|
headers = state.request.headers
|
||||||
|
user_id = headers.get('X-User-Id')
|
||||||
|
user_id = headers.get('X-User', user_id)
|
||||||
|
tenant = state.request.headers.get('X-Tenant-Id')
|
||||||
|
tenant = state.request.headers.get('X-Tenant', tenant)
|
||||||
|
domain_id = state.request.headers.get('X-User-Domain-Id')
|
||||||
|
domain_name = state.request.headers.get('X-User-Domain-Name')
|
||||||
|
auth_token = state.request.headers.get('X-Storage-Token')
|
||||||
|
auth_token = state.request.headers.get('X-Auth-Token', auth_token)
|
||||||
|
auth_token_info = state.request.environ.get('keystone.token_info')
|
||||||
|
|
||||||
|
auth_url = headers.get('X-Auth-Url')
|
||||||
|
if auth_url is None:
|
||||||
|
importutils.import_module('keystonemiddleware.auth_token')
|
||||||
|
auth_url = cfg.CONF.keystone_authtoken.auth_uri
|
||||||
|
|
||||||
|
state.request.context = context.RequestContext(
|
||||||
|
auth_token=auth_token,
|
||||||
|
auth_url=auth_url,
|
||||||
|
auth_token_info=auth_token_info,
|
||||||
|
user=user_id,
|
||||||
|
tenant=tenant,
|
||||||
|
domain_id=domain_id,
|
||||||
|
domain_name=domain_name)
|
20
magnum/api/middleware/__init__.py
Normal file
20
magnum/api/middleware/__init__.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# 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 magnum.api.middleware import auth_token
|
||||||
|
|
||||||
|
|
||||||
|
AuthTokenMiddleware = auth_token.AuthTokenMiddleware
|
||||||
|
|
||||||
|
__all__ = (AuthTokenMiddleware)
|
60
magnum/api/middleware/auth_token.py
Normal file
60
magnum/api/middleware/auth_token.py
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
# -*- encoding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# 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 re
|
||||||
|
|
||||||
|
from keystonemiddleware import auth_token
|
||||||
|
|
||||||
|
from magnum.common import exception
|
||||||
|
from magnum.common import utils
|
||||||
|
from magnum.openstack.common._i18n import _
|
||||||
|
from magnum.openstack.common import log
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class AuthTokenMiddleware(auth_token.AuthProtocol):
|
||||||
|
"""A wrapper on Keystone auth_token middleware.
|
||||||
|
|
||||||
|
Does not perform verification of authentication tokens
|
||||||
|
for public routes in the API.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, app, conf, public_api_routes=[]):
|
||||||
|
route_pattern_tpl = '%s(\.json|\.xml)?$'
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.public_api_routes = [re.compile(route_pattern_tpl % route_tpl)
|
||||||
|
for route_tpl in public_api_routes]
|
||||||
|
except re.error as e:
|
||||||
|
msg = _('Cannot compile public API routes: %s') % e
|
||||||
|
|
||||||
|
LOG.error(msg)
|
||||||
|
raise exception.ConfigInvalid(error_msg=msg)
|
||||||
|
|
||||||
|
super(AuthTokenMiddleware, self).__init__(app, conf)
|
||||||
|
|
||||||
|
def __call__(self, env, start_response):
|
||||||
|
path = utils.safe_rstrip(env.get('PATH_INFO'), '/')
|
||||||
|
|
||||||
|
# The information whether the API call is being performed against the
|
||||||
|
# public API is required for some other components. Saving it to the
|
||||||
|
# WSGI environment is reasonable thereby.
|
||||||
|
env['is_public_api'] = any(map(lambda pattern: re.match(pattern, path),
|
||||||
|
self.public_api_routes))
|
||||||
|
|
||||||
|
if env['is_public_api']:
|
||||||
|
return self._app(env, start_response)
|
||||||
|
|
||||||
|
return super(AuthTokenMiddleware, self).__call__(env, start_response)
|
@ -14,8 +14,8 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
from magnum.api import app as api_app
|
from magnum.api import app as api_app
|
||||||
from magnum.api import auth
|
|
||||||
from magnum.api import config as api_config
|
from magnum.api import config as api_config
|
||||||
|
from magnum.api import hooks
|
||||||
from magnum.tests import base
|
from magnum.tests import base
|
||||||
|
|
||||||
|
|
||||||
@ -30,4 +30,4 @@ class TestAppConfig(base.BaseTestCase):
|
|||||||
|
|
||||||
self.assertEqual(config_d['modules'], api_config.app['modules'])
|
self.assertEqual(config_d['modules'], api_config.app['modules'])
|
||||||
self.assertEqual(config_d['root'], api_config.app['root'])
|
self.assertEqual(config_d['root'], api_config.app['root'])
|
||||||
self.assertIsInstance(config_d['hooks'][0], auth.AuthInformationHook)
|
self.assertIsInstance(config_d['hooks'][0], hooks.ContextHook)
|
||||||
|
@ -17,12 +17,11 @@ import mock
|
|||||||
from oslo.config import fixture
|
from oslo.config import fixture
|
||||||
|
|
||||||
from magnum.api import auth
|
from magnum.api import auth
|
||||||
from magnum.common import context
|
|
||||||
from magnum.tests import base
|
from magnum.tests import base
|
||||||
from magnum.tests import fakes
|
from magnum.tests import fakes
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('magnum.api.auth.AuthProtocolWrapper',
|
@mock.patch('magnum.api.middleware.auth_token.AuthTokenMiddleware',
|
||||||
new_callable=fakes.FakeAuthProtocol)
|
new_callable=fakes.FakeAuthProtocol)
|
||||||
class TestAuth(base.BaseTestCase):
|
class TestAuth(base.BaseTestCase):
|
||||||
|
|
||||||
@ -32,51 +31,11 @@ class TestAuth(base.BaseTestCase):
|
|||||||
self.app = fakes.FakeApp()
|
self.app = fakes.FakeApp()
|
||||||
|
|
||||||
def test_check_auth_option_enabled(self, mock_auth):
|
def test_check_auth_option_enabled(self, mock_auth):
|
||||||
|
|
||||||
self.CONF.config(auth_protocol="footp",
|
|
||||||
auth_version="v2.0",
|
|
||||||
auth_uri=None,
|
|
||||||
group=auth.OPT_GROUP_NAME)
|
|
||||||
self.CONF.config(enable_authentication=True)
|
self.CONF.config(enable_authentication=True)
|
||||||
result = auth.install(self.app, self.CONF.conf)
|
result = auth.install(self.app, self.CONF.conf, ['/'])
|
||||||
self.assertIsInstance(result, fakes.FakeAuthProtocol)
|
self.assertIsInstance(result, fakes.FakeAuthProtocol)
|
||||||
|
|
||||||
def test_check_auth_option_disabled(self, mock_auth):
|
def test_check_auth_option_disabled(self, mock_auth):
|
||||||
self.CONF.config(auth_protocol="footp",
|
|
||||||
auth_version="v2.0",
|
|
||||||
auth_uri=None,
|
|
||||||
group=auth.OPT_GROUP_NAME)
|
|
||||||
self.CONF.config(enable_authentication=False)
|
self.CONF.config(enable_authentication=False)
|
||||||
result = auth.install(self.app, self.CONF.conf)
|
result = auth.install(self.app, self.CONF.conf, ['/'])
|
||||||
self.assertIsInstance(result, fakes.FakeApp)
|
self.assertIsInstance(result, fakes.FakeApp)
|
||||||
|
|
||||||
def test_auth_hook_before_method(self, mock_cls):
|
|
||||||
state = mock.Mock(request=fakes.FakePecanRequest())
|
|
||||||
hook = auth.AuthInformationHook()
|
|
||||||
hook.before(state)
|
|
||||||
ctx = state.request.context
|
|
||||||
self.assertIsInstance(ctx, context.RequestContext)
|
|
||||||
self.assertEqual(ctx.auth_token,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-Auth-Token'])
|
|
||||||
self.assertEqual(ctx.tenant,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-Tenant-Id'])
|
|
||||||
self.assertEqual(ctx.user,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-User-Id'])
|
|
||||||
self.assertEqual(ctx.auth_url,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-Auth-Url'])
|
|
||||||
self.assertEqual(ctx.domain_name,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-User-Domain-Name'])
|
|
||||||
self.assertEqual(ctx.domain_id,
|
|
||||||
fakes.fakeAuthTokenHeaders['X-User-Domain-Id'])
|
|
||||||
self.assertIsNone(ctx.auth_token_info)
|
|
||||||
|
|
||||||
def test_auth_hook_before_method_auth_info(self, mock_cls):
|
|
||||||
state = mock.Mock(request=fakes.FakePecanRequest())
|
|
||||||
state.request.environ['keystone.token_info'] = 'assert_this'
|
|
||||||
hook = auth.AuthInformationHook()
|
|
||||||
hook.before(state)
|
|
||||||
ctx = state.request.context
|
|
||||||
self.assertIsInstance(ctx, context.RequestContext)
|
|
||||||
self.assertEqual(fakes.fakeAuthTokenHeaders['X-Auth-Token'],
|
|
||||||
ctx.auth_token)
|
|
||||||
self.assertEqual('assert_this', ctx.auth_token_info)
|
|
||||||
|
59
magnum/tests/api/test_hooks.py
Normal file
59
magnum/tests/api/test_hooks.py
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
# Copyright 2014
|
||||||
|
# The Cloudscaling Group, 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 mock
|
||||||
|
|
||||||
|
from magnum.api import hooks
|
||||||
|
from magnum.common import context
|
||||||
|
from magnum.tests import base
|
||||||
|
from magnum.tests import fakes
|
||||||
|
|
||||||
|
|
||||||
|
class TestHooks(base.BaseTestCase):
|
||||||
|
|
||||||
|
def setUp(self):
|
||||||
|
super(TestHooks, self).setUp()
|
||||||
|
self.app = fakes.FakeApp()
|
||||||
|
|
||||||
|
def test_context_hook_before_method(self):
|
||||||
|
state = mock.Mock(request=fakes.FakePecanRequest())
|
||||||
|
hook = hooks.ContextHook()
|
||||||
|
hook.before(state)
|
||||||
|
ctx = state.request.context
|
||||||
|
self.assertIsInstance(ctx, context.RequestContext)
|
||||||
|
self.assertEqual(ctx.auth_token,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-Auth-Token'])
|
||||||
|
self.assertEqual(ctx.tenant,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-Tenant-Id'])
|
||||||
|
self.assertEqual(ctx.user,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-User-Id'])
|
||||||
|
self.assertEqual(ctx.auth_url,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-Auth-Url'])
|
||||||
|
self.assertEqual(ctx.domain_name,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-User-Domain-Name'])
|
||||||
|
self.assertEqual(ctx.domain_id,
|
||||||
|
fakes.fakeAuthTokenHeaders['X-User-Domain-Id'])
|
||||||
|
self.assertIsNone(ctx.auth_token_info)
|
||||||
|
|
||||||
|
def test_context_hook_before_method_auth_info(self):
|
||||||
|
state = mock.Mock(request=fakes.FakePecanRequest())
|
||||||
|
state.request.environ['keystone.token_info'] = 'assert_this'
|
||||||
|
hook = hooks.ContextHook()
|
||||||
|
hook.before(state)
|
||||||
|
ctx = state.request.context
|
||||||
|
self.assertIsInstance(ctx, context.RequestContext)
|
||||||
|
self.assertEqual(fakes.fakeAuthTokenHeaders['X-Auth-Token'],
|
||||||
|
ctx.auth_token)
|
||||||
|
self.assertEqual('assert_this', ctx.auth_token_info)
|
@ -10,6 +10,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
|
|
||||||
|
from magnum.api import hooks
|
||||||
|
|
||||||
# Server Specific Configurations
|
# Server Specific Configurations
|
||||||
server = {
|
server = {
|
||||||
'port': '8080',
|
'port': '8080',
|
||||||
@ -20,13 +22,13 @@ server = {
|
|||||||
app = {
|
app = {
|
||||||
'root': 'magnum.api.controllers.root.RootController',
|
'root': 'magnum.api.controllers.root.RootController',
|
||||||
'modules': ['magnum.api'],
|
'modules': ['magnum.api'],
|
||||||
'static_root': '%(confdir)s/../../public',
|
|
||||||
'template_path': '%(confdir)s/../templates',
|
|
||||||
'debug': True,
|
'debug': True,
|
||||||
'errors': {
|
'hooks': [
|
||||||
'404': '/error/404',
|
hooks.ContextHook(),
|
||||||
'__force_dict__': True
|
],
|
||||||
}
|
'acl_public_routes': [
|
||||||
|
'/'
|
||||||
|
],
|
||||||
}
|
}
|
||||||
|
|
||||||
# Custom Configurations must be in Python dictionary format::
|
# Custom Configurations must be in Python dictionary format::
|
||||||
|
Loading…
Reference in New Issue
Block a user