Merge "add no authentication for vitrage"
This commit is contained in:
commit
40fb89d4bf
@ -1,14 +1,41 @@
|
||||
# Remove keystone_authtoken from the pipeline if you don't want to use keystone authentication
|
||||
[pipeline:main]
|
||||
pipeline = cors keystone_authtoken vitrage
|
||||
[composite:vitrage+noauth]
|
||||
use = egg:Paste#urlmap
|
||||
/ = vitrageversions_pipeline
|
||||
/v1 = vitragev1_noauth_pipeline
|
||||
|
||||
[app:vitrage]
|
||||
[composite:vitrage+keystone]
|
||||
use = egg:Paste#urlmap
|
||||
/ = vitrageversions_pipeline
|
||||
/v1 = vitragev1_keystone_pipeline
|
||||
|
||||
[pipeline:vitrageversions_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi vitrageversions
|
||||
|
||||
[app:vitrageversions]
|
||||
paste.app_factory = vitrage.api.app:app_factory
|
||||
root = vitrage.api.controllers.root.VersionsController
|
||||
|
||||
[filter:keystone_authtoken]
|
||||
[pipeline:vitragev1_keystone_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi request_id authtoken vitragev1
|
||||
|
||||
[pipeline:vitragev1_noauth_pipeline]
|
||||
pipeline = cors http_proxy_to_wsgi request_id vitragev1
|
||||
|
||||
[app:vitragev1]
|
||||
paste.app_factory = vitrage.api.app:app_factory
|
||||
root = vitrage.api.controllers.v1.root.V1Controller
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
oslo_config_project = vitrage
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = vitrage
|
||||
oslo_config_project = vitrage
|
||||
|
||||
[filter:http_proxy_to_wsgi]
|
||||
paste.filter_factory = oslo_middleware.http_proxy_to_wsgi:HTTPProxyToWSGI.factory
|
||||
oslo_config_project = vitrage
|
||||
|
@ -17,21 +17,16 @@ from oslo_config import cfg
|
||||
|
||||
# Register options for the service
|
||||
OPTS = [
|
||||
cfg.PortOpt('port',
|
||||
default=8999,
|
||||
help='The port for the vitrage API server.',
|
||||
),
|
||||
cfg.StrOpt('host',
|
||||
default='0.0.0.0',
|
||||
help='The listen IP for the vitrage API server.',
|
||||
),
|
||||
cfg.PortOpt('port', default=8999,
|
||||
help='The port for the vitrage API server.',),
|
||||
cfg.StrOpt('host', default='0.0.0.0',
|
||||
help='The listen IP for the vitrage API server.',),
|
||||
cfg.StrOpt('paste_config', default='api-paste.ini',
|
||||
help='Configuration file for WSGI definition of API.'),
|
||||
|
||||
cfg.IntOpt('workers', default=1,
|
||||
min=1,
|
||||
cfg.IntOpt('workers', default=1, min=1,
|
||||
help='Number of workers for vitrage API server.'),
|
||||
|
||||
cfg.BoolOpt('pecan_debug', default=False,
|
||||
help='Toggle Pecan Debug Middleware.'),
|
||||
cfg.StrOpt('auth_mode', default='keystone', choices={'keystone', 'noauth'},
|
||||
help='Authentication mode to use.'),
|
||||
]
|
||||
|
@ -11,6 +11,8 @@
|
||||
# under the License.
|
||||
|
||||
import os
|
||||
import uuid
|
||||
|
||||
import pecan
|
||||
|
||||
from oslo_config import cfg
|
||||
@ -20,36 +22,27 @@ from paste import deploy
|
||||
from werkzeug import serving
|
||||
|
||||
from vitrage.api import hooks
|
||||
from vitrage import service
|
||||
|
||||
LOG = log.getLogger(__name__)
|
||||
|
||||
PECAN_CONFIG = {
|
||||
'app': {
|
||||
'root': 'vitrage.api.controllers.root.RootController',
|
||||
'modules': ['vitrage.api'],
|
||||
},
|
||||
}
|
||||
# NOTE(sileht): pastedeploy uses ConfigParser to handle
|
||||
# global_conf, since python 3 ConfigParser doesn't
|
||||
# allow storing object as config value, only strings are
|
||||
# permit, so to be able to pass an object created before paste load
|
||||
# the app, we store them into a global var. But the each loaded app
|
||||
# store it's configuration in unique key to be concurrency safe.
|
||||
global APPCONFIGS
|
||||
APPCONFIGS = {}
|
||||
|
||||
|
||||
def setup_app(pecan_config=PECAN_CONFIG, conf=None):
|
||||
if conf is None:
|
||||
raise RuntimeError('Config is actually mandatory')
|
||||
def setup_app(root, conf=None):
|
||||
app_hooks = [hooks.ConfigHook(conf),
|
||||
hooks.TranslationHook(),
|
||||
hooks.RPCHook(conf),
|
||||
hooks.ContextHook()]
|
||||
|
||||
pecan.configuration.set_config(dict(pecan_config), overwrite=True)
|
||||
pecan_debug = conf.api.pecan_debug
|
||||
if conf.api.workers != 1 and pecan_debug:
|
||||
pecan_debug = False
|
||||
LOG.warning('pecan_debug cannot be enabled, if workers is > 1, '
|
||||
'the value is overridden with False')
|
||||
|
||||
app = pecan.make_app(
|
||||
pecan_config['app']['root'],
|
||||
debug=pecan_debug,
|
||||
root,
|
||||
hooks=app_hooks,
|
||||
guess_content_type_from_ext=False
|
||||
)
|
||||
@ -58,18 +51,25 @@ def setup_app(pecan_config=PECAN_CONFIG, conf=None):
|
||||
|
||||
|
||||
def load_app(conf):
|
||||
global APPCONFIGS
|
||||
|
||||
# Build the WSGI app
|
||||
cfg_file = None
|
||||
cfg_path = conf.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
|
||||
cfg_path = conf.find_file(cfg_path)
|
||||
|
||||
if not cfg_file:
|
||||
if cfg_path is None or not os.path.exists(cfg_path):
|
||||
raise cfg.ConfigFilesNotFoundError([conf.api.paste_config])
|
||||
LOG.info('Full WSGI config used: %s', cfg_file)
|
||||
return deploy.loadapp("config:" + cfg_file)
|
||||
|
||||
config = dict(conf=conf)
|
||||
configkey = str(uuid.uuid4())
|
||||
APPCONFIGS[configkey] = config
|
||||
|
||||
LOG.info('Full WSGI config used: %s', cfg_path)
|
||||
|
||||
appname = "vitrage+" + conf.api.auth_mode
|
||||
return deploy.loadapp("config:" + cfg_path, name=appname,
|
||||
global_conf={'configkey': configkey})
|
||||
|
||||
|
||||
def build_server(conf):
|
||||
@ -93,10 +93,7 @@ def build_server(conf):
|
||||
app, processes=conf.api.workers)
|
||||
|
||||
|
||||
def _app():
|
||||
conf = service.prepare_service()
|
||||
return setup_app(conf=conf)
|
||||
|
||||
|
||||
def app_factory(global_config, **local_conf):
|
||||
return _app()
|
||||
global APPCONFIGS
|
||||
appconfig = APPCONFIGS.get(global_config.get('configkey'))
|
||||
return setup_app(root=local_conf.get('root'), **appconfig)
|
||||
|
@ -11,11 +11,9 @@
|
||||
# under the License.
|
||||
|
||||
import pecan as pecan
|
||||
from vitrage.api.controllers.v1 import root as v1
|
||||
|
||||
|
||||
class RootController(object):
|
||||
v1 = v1.V1Controller()
|
||||
class VersionsController(object):
|
||||
|
||||
@staticmethod
|
||||
@pecan.expose('json')
|
||||
|
@ -16,12 +16,13 @@
|
||||
# under the License.
|
||||
"""Base classes for API tests.
|
||||
"""
|
||||
|
||||
import os
|
||||
import pecan
|
||||
import pecan.testing
|
||||
|
||||
from oslo_config import fixture as fixture_config
|
||||
import sys
|
||||
import webtest
|
||||
|
||||
from vitrage.api import app
|
||||
from vitrage import service
|
||||
|
||||
from vitrage.tests import base
|
||||
@ -40,29 +41,24 @@ class FunctionalTest(base.BaseTest):
|
||||
def setUp(self):
|
||||
super(FunctionalTest, self).setUp()
|
||||
conf = service.prepare_service(args=[], config_files=[])
|
||||
self.conf = self.useFixture(fixture_config.Config(conf)).conf
|
||||
self.CONF = self.useFixture(fixture_config.Config(conf)).conf
|
||||
|
||||
self.conf.set_override('policy_file',
|
||||
os.path.abspath('etc/vitrage/policy.json'),
|
||||
group='oslo_policy')
|
||||
self.app = self._make_app()
|
||||
vitrage_init_file = sys.modules['vitrage'].__file__
|
||||
vitrage_root = os.path.abspath(
|
||||
os.path.join(os.path.dirname(vitrage_init_file), '..', ))
|
||||
|
||||
def _make_app(self):
|
||||
self.config = {
|
||||
'app': {
|
||||
'root': 'vitrage.api.controllers.root.RootController',
|
||||
'modules': ['vitrage.api'],
|
||||
},
|
||||
'wsme': {
|
||||
'debug': True,
|
||||
},
|
||||
}
|
||||
self.CONF.set_override('policy_file', os.path.join(vitrage_root,
|
||||
'etc', 'vitrage',
|
||||
'policy.json'),
|
||||
group='oslo_policy', enforce_type=True)
|
||||
|
||||
return pecan.testing.load_test_app(self.config, conf=self.conf)
|
||||
self.CONF.set_override('paste_config', os.path.join(vitrage_root,
|
||||
'etc', 'vitrage',
|
||||
'api-paste.ini'),
|
||||
group='api', enforce_type=True)
|
||||
|
||||
def tearDown(self):
|
||||
super(FunctionalTest, self).tearDown()
|
||||
pecan.set_config({}, overwrite=True)
|
||||
self.CONF.set_override('auth_mode', self.auth, group='api')
|
||||
self.app = webtest.TestApp(app.load_app(self.CONF))
|
||||
|
||||
def put_json(self, path, params, expect_errors=False, headers=None,
|
||||
extra_environ=None, status=None):
|
||||
|
@ -26,6 +26,11 @@ VERSIONS_RESPONSE = {u'versions': [{u'id': u'v1.0',
|
||||
|
||||
|
||||
class TestVersions(api.FunctionalTest):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
super(TestVersions, self).__init__(*args, **kwds)
|
||||
self.auth = 'keystone'
|
||||
|
||||
def test_versions(self):
|
||||
data = self.get_json('/')
|
||||
self.assertEqual(VERSIONS_RESPONSE, data)
|
||||
|
@ -15,23 +15,15 @@
|
||||
# limitations under the License.
|
||||
|
||||
# noinspection PyPackageRequirements
|
||||
import mock
|
||||
import webtest
|
||||
|
||||
from vitrage.api import app
|
||||
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||
|
||||
|
||||
class TestAuthentications(FunctionalTest):
|
||||
def _make_app(self):
|
||||
file_name = self.path_get('etc/vitrage/api-paste.ini')
|
||||
self.conf.set_override("paste_config", file_name, "api")
|
||||
# We need the other call to prepare_service in app.py to return the
|
||||
# same tweaked conf object.
|
||||
with mock.patch('vitrage.service.prepare_service') as ps:
|
||||
ps.return_value = self.conf
|
||||
return webtest.TestApp(app.load_app(conf=self.conf))
|
||||
class AuthTest(FunctionalTest):
|
||||
|
||||
def test_not_authenticated(self):
|
||||
def __init__(self, *args, **kwds):
|
||||
super(AuthTest, self).__init__(*args, **kwds)
|
||||
self.auth = 'keystone'
|
||||
|
||||
def test_in_keystone_mode_not_authenticated(self):
|
||||
resp = self.post_json('/topology/', params=None, expect_errors=True)
|
||||
self.assertEqual(401, resp.status_int)
|
||||
self.assertEqual('401 Unauthorized', resp.status)
|
135
vitrage/tests/functional/api/v1/test_noauth.py
Normal file
135
vitrage/tests/functional/api/v1/test_noauth.py
Normal file
@ -0,0 +1,135 @@
|
||||
# Copyright 2016 - Nokia Corporation
|
||||
# Copyright 2014 OpenStack Foundation
|
||||
#
|
||||
# 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 datetime import datetime
|
||||
# noinspection PyPackageRequirements
|
||||
from mock import mock
|
||||
|
||||
from vitrage.tests.functional.api.v1 import FunctionalTest
|
||||
|
||||
|
||||
class NoAuthTest(FunctionalTest):
|
||||
|
||||
def __init__(self, *args, **kwds):
|
||||
super(NoAuthTest, self).__init__(*args, **kwds)
|
||||
self.auth = 'noauth'
|
||||
|
||||
def test_noauth_mode_post_event(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
|
||||
details = {
|
||||
'hostname': 'host123',
|
||||
'source': 'sample_monitor',
|
||||
'cause': 'another alarm',
|
||||
'severity': 'critical',
|
||||
'status': 'down',
|
||||
'monitor_id': 'sample monitor',
|
||||
'monitor_event_id': '456',
|
||||
}
|
||||
event_time = datetime.now().isoformat()
|
||||
event_type = 'compute.host.down'
|
||||
|
||||
resp = self.post_json('/event/', params={'time': event_time,
|
||||
'type': event_type,
|
||||
'details': details})
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual('200 OK', resp.status)
|
||||
|
||||
def test_noauth_mode_get_topology(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{}'
|
||||
params = dict(depth=None, graph_type='graph', query=None,
|
||||
root=None,
|
||||
all_tenants=False)
|
||||
resp = self.post_json('/topology/', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual('200 OK', resp.status)
|
||||
self.assertEqual({}, resp.json)
|
||||
|
||||
def test_noauth_mode_list_alarms(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{"alarms": []}'
|
||||
params = dict(vitrage_id='all', all_tenants=False)
|
||||
resp = self.post_json('/alarm/', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual('200 OK', resp.status)
|
||||
self.assertEqual([], resp.json)
|
||||
|
||||
def test_noauth_mode_list_resources(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{"resources": []}'
|
||||
params = dict(resource_type='all', all_tenants=False)
|
||||
data = self.get_json('/resources/', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual([], data)
|
||||
|
||||
def test_noauth_mode_show_resource(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{}'
|
||||
params = dict(resource_type='all', all_tenants=False)
|
||||
data = self.get_json('/resources/1234', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual({}, data)
|
||||
|
||||
def test_noauth_mode_list_templates(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{"templates_details": []}'
|
||||
data = self.get_json('/template/')
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual([], data)
|
||||
|
||||
def test_noauth_mode_show_template(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{}'
|
||||
data = self.get_json('/template/1234')
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual({}, data)
|
||||
|
||||
def test_noauth_mode_validate_template(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{}'
|
||||
params = {"templates": {}}
|
||||
resp = self.post_json('/template/', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual('200 OK', resp.status)
|
||||
self.assertEqual({}, resp.json)
|
||||
|
||||
def test_noauth_mode_get_rca(self):
|
||||
|
||||
with mock.patch('pecan.request') as request:
|
||||
request.client.call.return_value = '{}'
|
||||
params = dict(all_tenants=False)
|
||||
data = self.get_json('/rca/1234/', params=params)
|
||||
|
||||
self.assertEqual(1, request.client.call.call_count)
|
||||
self.assertEqual({}, data)
|
Loading…
x
Reference in New Issue
Block a user