Load wsgi app(api) with paste.deploy
This change replaces the hard coded WSGI app creation with a pipeline of WSGI apps declared in a configuration file. Paste Deploy was used to create the pipeline since it is used by many other OpenStack projects and it is an active project with new contributors and supports Python 3. Dependency on Paste is localized so switching to another library would not be hard if OpenStack moves to another package in the future. Change-Id: I9a45f974c2c8c67a01748583639e6a6248003b85 Closes-Bug:#1551134
This commit is contained in:
parent
0563743f4d
commit
db378a0ee5
|
@ -44,6 +44,7 @@ MAGNUM_AUTH_CACHE_DIR=${MAGNUM_AUTH_CACHE_DIR:-/var/cache/magnum}
|
||||||
MAGNUM_CONF_DIR=/etc/magnum
|
MAGNUM_CONF_DIR=/etc/magnum
|
||||||
MAGNUM_CONF=$MAGNUM_CONF_DIR/magnum.conf
|
MAGNUM_CONF=$MAGNUM_CONF_DIR/magnum.conf
|
||||||
MAGNUM_POLICY_JSON=$MAGNUM_CONF_DIR/policy.json
|
MAGNUM_POLICY_JSON=$MAGNUM_CONF_DIR/policy.json
|
||||||
|
MAGNUM_API_PASTE=$MAGNUM_CONF_DIR/api-paste.ini
|
||||||
|
|
||||||
if is_ssl_enabled_service "magnum" || is_service_enabled tls-proxy; then
|
if is_ssl_enabled_service "magnum" || is_service_enabled tls-proxy; then
|
||||||
MAGNUM_SERVICE_PROTOCOL="https"
|
MAGNUM_SERVICE_PROTOCOL="https"
|
||||||
|
@ -95,6 +96,8 @@ function configure_magnum {
|
||||||
# Rebuild the config file from scratch
|
# Rebuild the config file from scratch
|
||||||
create_magnum_conf
|
create_magnum_conf
|
||||||
|
|
||||||
|
create_api_paste_conf
|
||||||
|
|
||||||
update_heat_policy
|
update_heat_policy
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,6 +209,11 @@ function create_magnum_conf {
|
||||||
iniset $MAGNUM_CONF cinder_client region_name $REGION_NAME
|
iniset $MAGNUM_CONF cinder_client region_name $REGION_NAME
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function create_api_paste_conf {
|
||||||
|
# copy api_paste.ini
|
||||||
|
cp $MAGNUM_DIR/etc/magnum/api-paste.ini $MAGNUM_API_PASTE
|
||||||
|
}
|
||||||
|
|
||||||
function update_heat_policy {
|
function update_heat_policy {
|
||||||
# enable stacks globel_index search so that magnum can use
|
# enable stacks globel_index search so that magnum can use
|
||||||
# list(global_tenant=True)
|
# list(global_tenant=True)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
[pipeline:main]
|
||||||
|
pipeline = cors request_id authtoken api_v1
|
||||||
|
|
||||||
|
[app:api_v1]
|
||||||
|
paste.app_factory = magnum.api.app:app_factory
|
||||||
|
|
||||||
|
[filter:authtoken]
|
||||||
|
acl_public_routes = /, /v1
|
||||||
|
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||||
|
|
||||||
|
[filter:request_id]
|
||||||
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
[filter:cors]
|
||||||
|
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||||
|
oslo_config_project = magnum
|
||||||
|
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
||||||
|
latent_allow_headers = X-Auth-Token, X-Identity-Status, X-Roles, X-Service-Catalog, X-User-Id, X-Tenant-Id, X-OpenStack-Request-ID
|
||||||
|
latent_expose_headers = X-Auth-Token, X-Subject-Token, X-Service-Token, X-OpenStack-Request-ID
|
|
@ -9,14 +9,16 @@
|
||||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
# 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.
|
||||||
|
import os
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_middleware import cors
|
from oslo_log import log
|
||||||
|
from paste import deploy
|
||||||
import pecan
|
import pecan
|
||||||
|
|
||||||
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 middleware
|
from magnum.api import middleware
|
||||||
|
from magnum.i18n import _
|
||||||
|
|
||||||
# Register options for the service
|
# Register options for the service
|
||||||
API_SERVICE_OPTS = [
|
API_SERVICE_OPTS = [
|
||||||
|
@ -29,7 +31,11 @@ API_SERVICE_OPTS = [
|
||||||
cfg.IntOpt('max_limit',
|
cfg.IntOpt('max_limit',
|
||||||
default=1000,
|
default=1000,
|
||||||
help='The maximum number of items returned in a single '
|
help='The maximum number of items returned in a single '
|
||||||
'response from a collection resource.')
|
'response from a collection resource.'),
|
||||||
|
cfg.StrOpt('api_paste_config',
|
||||||
|
default="api-paste.ini",
|
||||||
|
help="Configuration file for WSGI definition of API."
|
||||||
|
)
|
||||||
]
|
]
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
@ -38,6 +44,8 @@ opt_group = cfg.OptGroup(name='api',
|
||||||
CONF.register_group(opt_group)
|
CONF.register_group(opt_group)
|
||||||
CONF.register_opts(API_SERVICE_OPTS, opt_group)
|
CONF.register_opts(API_SERVICE_OPTS, opt_group)
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
def get_pecan_config():
|
def get_pecan_config():
|
||||||
# Set up the pecan configuration
|
# Set up the pecan configuration
|
||||||
|
@ -58,17 +66,22 @@ def setup_app(config=None):
|
||||||
**app_conf
|
**app_conf
|
||||||
)
|
)
|
||||||
|
|
||||||
app = auth.install(app, CONF, config.app.acl_public_routes)
|
|
||||||
|
|
||||||
# CORS must be the last one.
|
|
||||||
app = cors.CORS(app, CONF)
|
|
||||||
app.set_latent(
|
|
||||||
allow_headers=['X-Auth-Token', 'X-Identity-Status', 'X-Roles',
|
|
||||||
'X-Service-Catalog', 'X-User-Id', 'X-Tenant-Id',
|
|
||||||
'X-OpenStack-Request-ID', 'X-Server-Management-Url'],
|
|
||||||
allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'],
|
|
||||||
expose_headers=['X-Auth-Token', 'X-Subject-Token', 'X-Service-Token',
|
|
||||||
'X-OpenStack-Request-ID', 'X-Server-Management-Url']
|
|
||||||
)
|
|
||||||
|
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
def load_app():
|
||||||
|
cfg_file = None
|
||||||
|
cfg_path = cfg.CONF.api.api_paste_config
|
||||||
|
if not os.path.isabs(cfg_path):
|
||||||
|
cfg_file = CONF.find_file(cfg_path)
|
||||||
|
elif os.path.exists(cfg_path):
|
||||||
|
cfg_file = cfg_path
|
||||||
|
|
||||||
|
if not cfg_file:
|
||||||
|
raise cfg.ConfigFilesNotFoundError([cfg.CONF.api_paste_config])
|
||||||
|
LOG.info(_("Full WSGI config used: %s") % cfg_file)
|
||||||
|
return deploy.loadapp("config:" + cfg_file)
|
||||||
|
|
||||||
|
|
||||||
|
def app_factory(global_config, **local_conf):
|
||||||
|
return setup_app()
|
||||||
|
|
|
@ -1,46 +0,0 @@
|
||||||
# Copyright 2012 New Dream Network, LLC (DreamHost)
|
|
||||||
#
|
|
||||||
# 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.
|
|
||||||
|
|
||||||
"""Access Control Lists (ACL's) control access the API server."""
|
|
||||||
from oslo_config import cfg
|
|
||||||
|
|
||||||
from magnum.api.middleware import auth_token
|
|
||||||
|
|
||||||
|
|
||||||
AUTH_OPTS = [
|
|
||||||
cfg.BoolOpt('enable_authentication',
|
|
||||||
default=True,
|
|
||||||
help='This option enables or disables user authentication '
|
|
||||||
'via Keystone. Default value is True.'),
|
|
||||||
]
|
|
||||||
|
|
||||||
CONF = cfg.CONF
|
|
||||||
CONF.register_opts(AUTH_OPTS)
|
|
||||||
|
|
||||||
|
|
||||||
def install(app, conf, public_routes):
|
|
||||||
"""Install ACL check on application.
|
|
||||||
|
|
||||||
:param app: A WSGI application.
|
|
||||||
:param conf: Settings. Dict'ified and passed to keystone middleware
|
|
||||||
:param public_routes: The list of the routes which will be allowed to
|
|
||||||
access without authentication.
|
|
||||||
:return: The same WSGI application with ACL installed.
|
|
||||||
|
|
||||||
"""
|
|
||||||
if not cfg.CONF.get('enable_authentication'):
|
|
||||||
return app
|
|
||||||
return auth_token.AuthTokenMiddleware(app,
|
|
||||||
conf=dict(conf),
|
|
||||||
public_api_routes=public_routes)
|
|
|
@ -58,3 +58,12 @@ class AuthTokenMiddleware(auth_token.AuthProtocol):
|
||||||
return self._app(env, start_response)
|
return self._app(env, start_response)
|
||||||
|
|
||||||
return super(AuthTokenMiddleware, self).__call__(env, start_response)
|
return super(AuthTokenMiddleware, self).__call__(env, start_response)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def factory(cls, global_config, **local_conf):
|
||||||
|
public_routes = local_conf.get('acl_public_routes', '')
|
||||||
|
public_api_routes = [path.strip() for path in public_routes.split(',')]
|
||||||
|
|
||||||
|
def _factory(app):
|
||||||
|
return cls(app, global_config, public_api_routes=public_api_routes)
|
||||||
|
return _factory
|
||||||
|
|
|
@ -40,7 +40,7 @@ def main():
|
||||||
# Enable object backporting via the conductor
|
# Enable object backporting via the conductor
|
||||||
base.MagnumObject.indirection_api = base.MagnumObjectIndirectionAPI()
|
base.MagnumObject.indirection_api = base.MagnumObjectIndirectionAPI()
|
||||||
|
|
||||||
app = api_app.setup_app()
|
app = api_app.load_app()
|
||||||
|
|
||||||
# Create the WSGI server and start it
|
# Create the WSGI server and start it
|
||||||
host, port = cfg.CONF.api.host, cfg.CONF.api.port
|
host, port = cfg.CONF.api.host, cfg.CONF.api.port
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
import magnum.api.app
|
import magnum.api.app
|
||||||
import magnum.api.auth
|
|
||||||
import magnum.api.validation
|
import magnum.api.validation
|
||||||
import magnum.common.cert_manager
|
import magnum.common.cert_manager
|
||||||
from magnum.common.cert_manager import local_cert_manager
|
from magnum.common.cert_manager import local_cert_manager
|
||||||
|
@ -35,8 +34,7 @@ import magnum.db
|
||||||
def list_opts():
|
def list_opts():
|
||||||
return [
|
return [
|
||||||
('DEFAULT',
|
('DEFAULT',
|
||||||
itertools.chain(magnum.api.auth.AUTH_OPTS,
|
itertools.chain(magnum.common.paths.PATH_OPTS,
|
||||||
magnum.common.paths.PATH_OPTS,
|
|
||||||
magnum.common.utils.UTILS_OPTS,
|
magnum.common.utils.UTILS_OPTS,
|
||||||
magnum.common.rpc_service.periodic_opts,
|
magnum.common.rpc_service.periodic_opts,
|
||||||
magnum.common.service.service_opts,
|
magnum.common.service.service_opts,
|
||||||
|
|
|
@ -54,8 +54,6 @@ class FunctionalTest(base.DbTestCase):
|
||||||
'modules': ['magnum.api'],
|
'modules': ['magnum.api'],
|
||||||
'static_root': '%s/public' % root_dir,
|
'static_root': '%s/public' % root_dir,
|
||||||
'template_path': '%s/api/templates' % root_dir,
|
'template_path': '%s/api/templates' % root_dir,
|
||||||
'enable_acl': False,
|
|
||||||
'acl_public_routes': ['/', '/v1'],
|
|
||||||
'hooks': [
|
'hooks': [
|
||||||
hooks.ContextHook(),
|
hooks.ContextHook(),
|
||||||
hooks.RPCHook(),
|
hooks.RPCHook(),
|
||||||
|
@ -83,12 +81,10 @@ class FunctionalTest(base.DbTestCase):
|
||||||
for attr in attrs:
|
for attr in attrs:
|
||||||
verify_method(attr, response)
|
verify_method(attr, response)
|
||||||
|
|
||||||
def _make_app(self, config=None, enable_acl=False):
|
def _make_app(self, config=None):
|
||||||
if not config:
|
if not config:
|
||||||
config = self.config
|
config = self.config
|
||||||
|
|
||||||
config["app"]["enable_acl"] = enable_acl
|
|
||||||
|
|
||||||
return pecan.testing.load_test_app(config)
|
return pecan.testing.load_test_app(config)
|
||||||
|
|
||||||
def _request_json(self, path, params, expect_errors=False, headers=None,
|
def _request_json(self, path, params, expect_errors=False, headers=None,
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
[pipeline:main]
|
||||||
|
pipeline = cors request_id authtoken api_v1
|
||||||
|
|
||||||
|
[app:api_v1]
|
||||||
|
paste.app_factory = magnum.api.app:app_factory
|
||||||
|
|
||||||
|
[filter:authtoken]
|
||||||
|
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||||
|
|
||||||
|
[filter:request_id]
|
||||||
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
[filter:cors]
|
||||||
|
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||||
|
oslo_config_project = magnum
|
||||||
|
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
||||||
|
latent_allow_headers = X-Auth-Token, X-Identity-Status, X-Roles, X-Service-Catalog, X-User-Id, X-Tenant-Id, X-OpenStack-Request-ID
|
||||||
|
latent_expose_headers = X-Auth-Token, X-Subject-Token, X-Service-Token, X-OpenStack-Request-ID
|
|
@ -0,0 +1,19 @@
|
||||||
|
[pipeline:main]
|
||||||
|
pipeline = cors request_id authtoken api_v1
|
||||||
|
|
||||||
|
[app:api_v1]
|
||||||
|
paste.app_factory = magnum.api.app:app_factory
|
||||||
|
|
||||||
|
[filter:authtoken]
|
||||||
|
acl_public_routes = /
|
||||||
|
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||||
|
|
||||||
|
[filter:request_id]
|
||||||
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
[filter:cors]
|
||||||
|
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||||
|
oslo_config_project = magnum
|
||||||
|
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
||||||
|
latent_allow_headers = X-Auth-Token, X-Identity-Status, X-Roles, X-Service-Catalog, X-User-Id, X-Tenant-Id, X-OpenStack-Request-ID
|
||||||
|
latent_expose_headers = X-Auth-Token, X-Subject-Token, X-Service-Token, X-OpenStack-Request-ID
|
|
@ -0,0 +1,19 @@
|
||||||
|
[pipeline:main]
|
||||||
|
pipeline = cors request_id authtoken api_v1
|
||||||
|
|
||||||
|
[app:api_v1]
|
||||||
|
paste.app_factory = magnum.api.app:app_factory
|
||||||
|
|
||||||
|
[filter:authtoken]
|
||||||
|
acl_public_routes = /v1
|
||||||
|
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||||
|
|
||||||
|
[filter:request_id]
|
||||||
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
[filter:cors]
|
||||||
|
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||||
|
oslo_config_project = magnum
|
||||||
|
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
||||||
|
latent_allow_headers = X-Auth-Token, X-Identity-Status, X-Roles, X-Service-Catalog, X-User-Id, X-Tenant-Id, X-OpenStack-Request-ID
|
||||||
|
latent_expose_headers = X-Auth-Token, X-Subject-Token, X-Service-Token, X-OpenStack-Request-ID
|
|
@ -0,0 +1,19 @@
|
||||||
|
[pipeline:main]
|
||||||
|
pipeline = cors request_id api_v1
|
||||||
|
|
||||||
|
[app:api_v1]
|
||||||
|
paste.app_factory = magnum.api.app:app_factory
|
||||||
|
|
||||||
|
[filter:authtoken]
|
||||||
|
acl_public_routes = /
|
||||||
|
paste.filter_factory = magnum.api.middleware.auth_token:AuthTokenMiddleware.factory
|
||||||
|
|
||||||
|
[filter:request_id]
|
||||||
|
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||||
|
|
||||||
|
[filter:cors]
|
||||||
|
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||||
|
oslo_config_project = magnum
|
||||||
|
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
||||||
|
latent_allow_headers = X-Auth-Token, X-Identity-Status, X-Roles, X-Service-Catalog, X-User-Id, X-Tenant-Id, X-OpenStack-Request-ID
|
||||||
|
latent_expose_headers = X-Auth-Token, X-Subject-Token, X-Service-Token, X-OpenStack-Request-ID
|
|
@ -10,12 +10,13 @@
|
||||||
# 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.
|
||||||
|
|
||||||
import copy
|
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from webob import exc as webob_exc
|
from webob import exc as webob_exc
|
||||||
|
|
||||||
|
import webtest
|
||||||
|
|
||||||
|
from magnum.api import app
|
||||||
from magnum.api.controllers import v1 as v1_api
|
from magnum.api.controllers import v1 as v1_api
|
||||||
from magnum.tests import base as test_base
|
from magnum.tests import base as test_base
|
||||||
from magnum.tests.unit.api import base as api_base
|
from magnum.tests.unit.api import base as api_base
|
||||||
|
@ -84,6 +85,11 @@ class TestRootController(api_base.FunctionalTest):
|
||||||
{u'href': u'http://localhost/mservices/',
|
{u'href': u'http://localhost/mservices/',
|
||||||
u'rel': u'bookmark'}]}
|
u'rel': u'bookmark'}]}
|
||||||
|
|
||||||
|
def make_app(self, paste_file):
|
||||||
|
file_name = self.get_path(paste_file)
|
||||||
|
cfg.CONF.set_override("api_paste_config", file_name, group="api")
|
||||||
|
return webtest.TestApp(app.load_app())
|
||||||
|
|
||||||
def test_version(self):
|
def test_version(self):
|
||||||
response = self.app.get('/')
|
response = self.app.get('/')
|
||||||
self.assertEqual(self.root_expected, response.json)
|
self.assertEqual(self.root_expected, response.json)
|
||||||
|
@ -96,13 +102,10 @@ class TestRootController(api_base.FunctionalTest):
|
||||||
response = self.app.get('/a/bogus/url', expect_errors=True)
|
response = self.app.get('/a/bogus/url', expect_errors=True)
|
||||||
assert response.status_int == 404
|
assert response.status_int == 404
|
||||||
|
|
||||||
def test_acl_access_with_all(self):
|
def test_noauth(self):
|
||||||
cfg.CONF.set_override("enable_authentication", True)
|
# Don't need to auth
|
||||||
|
paste_file = "magnum/tests/unit/api/controllers/noauth-paste.ini"
|
||||||
config = copy.deepcopy(self.config)
|
app = self.make_app(paste_file)
|
||||||
# Both / and /v1 and access without auth
|
|
||||||
config["app"]["acl_public_routes"] = ['/', '/v1']
|
|
||||||
app = self._make_app(config=config)
|
|
||||||
|
|
||||||
response = app.get('/')
|
response = app.get('/')
|
||||||
self.assertEqual(self.root_expected, response.json)
|
self.assertEqual(self.root_expected, response.json)
|
||||||
|
@ -110,13 +113,24 @@ class TestRootController(api_base.FunctionalTest):
|
||||||
response = app.get('/v1/')
|
response = app.get('/v1/')
|
||||||
self.assertEqual(self.v1_expected, response.json)
|
self.assertEqual(self.v1_expected, response.json)
|
||||||
|
|
||||||
def test_acl_access_with_root(self):
|
response = app.get('/v1/baymodels')
|
||||||
cfg.CONF.set_override("enable_authentication", True)
|
self.assertEqual(200, response.status_int)
|
||||||
|
|
||||||
config = copy.deepcopy(self.config)
|
def test_auth_with_no_public_routes(self):
|
||||||
|
# All apis need auth when access
|
||||||
|
paste_file = "magnum/tests/unit/api/controllers/auth-paste.ini"
|
||||||
|
app = self.make_app(paste_file)
|
||||||
|
|
||||||
|
response = app.get('/', expect_errors=True)
|
||||||
|
self.assertEqual(401, response.status_int)
|
||||||
|
|
||||||
|
response = app.get('/v1/', expect_errors=True)
|
||||||
|
self.assertEqual(401, response.status_int)
|
||||||
|
|
||||||
|
def test_auth_with_root_access(self):
|
||||||
# Only / can access without auth
|
# Only / can access without auth
|
||||||
config["app"]["acl_public_routes"] = ['/']
|
paste_file = "magnum/tests/unit/api/controllers/auth-root-access.ini"
|
||||||
app = self._make_app(config=config)
|
app = self.make_app(paste_file)
|
||||||
|
|
||||||
response = app.get('/')
|
response = app.get('/')
|
||||||
self.assertEqual(self.root_expected, response.json)
|
self.assertEqual(self.root_expected, response.json)
|
||||||
|
@ -124,13 +138,13 @@ class TestRootController(api_base.FunctionalTest):
|
||||||
response = app.get('/v1/', expect_errors=True)
|
response = app.get('/v1/', expect_errors=True)
|
||||||
self.assertEqual(401, response.status_int)
|
self.assertEqual(401, response.status_int)
|
||||||
|
|
||||||
def test_acl_access_with_v1(self):
|
response = app.get('/v1/baymodels', expect_errors=True)
|
||||||
cfg.CONF.set_override("enable_authentication", True)
|
self.assertEqual(401, response.status_int)
|
||||||
|
|
||||||
config = copy.deepcopy(self.config)
|
def test_auth_with_v1_access(self):
|
||||||
# Only /v1 can access without auth
|
# Only /v1 can access without auth
|
||||||
config["app"]["acl_public_routes"] = ['/v1']
|
paste_file = "magnum/tests/unit/api/controllers/auth-v1-access.ini"
|
||||||
app = self._make_app(config=config)
|
app = self.make_app(paste_file)
|
||||||
|
|
||||||
response = app.get('/', expect_errors=True)
|
response = app.get('/', expect_errors=True)
|
||||||
self.assertEqual(401, response.status_int)
|
self.assertEqual(401, response.status_int)
|
||||||
|
@ -138,17 +152,7 @@ class TestRootController(api_base.FunctionalTest):
|
||||||
response = app.get('/v1/')
|
response = app.get('/v1/')
|
||||||
self.assertEqual(self.v1_expected, response.json)
|
self.assertEqual(self.v1_expected, response.json)
|
||||||
|
|
||||||
def test_acl_with_neither(self):
|
response = app.get('/v1/baymodels', expect_errors=True)
|
||||||
cfg.CONF.set_override("enable_authentication", True)
|
|
||||||
|
|
||||||
config = copy.deepcopy(self.config)
|
|
||||||
config["app"]["acl_public_routes"] = []
|
|
||||||
app = self._make_app(config=config)
|
|
||||||
|
|
||||||
response = app.get('/', expect_errors=True)
|
|
||||||
self.assertEqual(401, response.status_int)
|
|
||||||
|
|
||||||
response = app.get('/v1/', expect_errors=True)
|
|
||||||
self.assertEqual(401, response.status_int)
|
self.assertEqual(401, response.status_int)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
# 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 oslo_config import fixture
|
|
||||||
|
|
||||||
from magnum.api import auth
|
|
||||||
from magnum.tests import base
|
|
||||||
from magnum.tests import fakes
|
|
||||||
|
|
||||||
|
|
||||||
@mock.patch('magnum.api.middleware.auth_token.AuthTokenMiddleware',
|
|
||||||
new_callable=fakes.FakeAuthProtocol)
|
|
||||||
class TestAuth(base.BaseTestCase):
|
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
super(TestAuth, self).setUp()
|
|
||||||
self.CONF = self.useFixture(fixture.Config())
|
|
||||||
self.app = fakes.FakeApp()
|
|
||||||
|
|
||||||
def test_check_auth_option_enabled(self, mock_auth):
|
|
||||||
self.CONF.config(enable_authentication=True)
|
|
||||||
result = auth.install(self.app, self.CONF.conf, ['/'])
|
|
||||||
self.assertIsInstance(result, fakes.FakeAuthProtocol)
|
|
||||||
|
|
||||||
def test_check_auth_option_disabled(self, mock_auth):
|
|
||||||
self.CONF.config(enable_authentication=False)
|
|
||||||
result = auth.install(self.app, self.CONF.conf, ['/'])
|
|
||||||
self.assertIsInstance(result, fakes.FakeApp)
|
|
|
@ -31,8 +31,6 @@ from magnum.tests import base
|
||||||
|
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
|
|
||||||
CONF.import_opt('enable_authentication', 'magnum.api.auth')
|
|
||||||
|
|
||||||
_DB_CACHE = None
|
_DB_CACHE = None
|
||||||
|
|
||||||
|
|
||||||
|
@ -88,7 +86,6 @@ class Database(fixtures.Fixture):
|
||||||
class DbTestCase(base.TestCase):
|
class DbTestCase(base.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
cfg.CONF.set_override("enable_authentication", False)
|
|
||||||
super(DbTestCase, self).setUp()
|
super(DbTestCase, self).setUp()
|
||||||
|
|
||||||
self.dbapi = dbapi.get_instance()
|
self.dbapi = dbapi.get_instance()
|
||||||
|
|
Loading…
Reference in New Issue