Added CORS support to Ceilometer
This adds the CORS support middleware to Ceilometer, allowing a deployer to optionally configure rules under which a javascript client may break the single-origin policy and access the API directly. Included are Ceilometer's custom headers, so that anyone activating this middleware does not have to explicitly enable them. The paste.ini method of deploying the middleware was chosen, because it needs to be able to annotate responses created by keystonemiddleware. OpenStack CrossProject Spec: http://specs.openstack.org/openstack/openstack-specs/specs/cors-support.html Oslo_Middleware Docs: http://docs.openstack.org/developer/oslo.middleware/cors.html OpenStack Cloud Admin Guide: http://docs.openstack.org/admin-guide-cloud/cross_project_cors.html Change-Id: I90d2a53c40e3c353abe3cf37bd7deb3a07aeb043
This commit is contained in:
parent
333024b69a
commit
45e1d22607
@ -22,6 +22,7 @@ from unittest import case
|
||||
import uuid
|
||||
|
||||
from gabbi import fixture
|
||||
from oslo_config import cfg
|
||||
from oslo_config import fixture as fixture_config
|
||||
from oslo_policy import opts
|
||||
from six.moves.urllib import parse as urlparse
|
||||
@ -64,6 +65,11 @@ class ConfigFixture(fixture.GabbiFixture):
|
||||
conf.set_override('policy_file',
|
||||
os.path.abspath('etc/ceilometer/policy.json'),
|
||||
group='oslo_policy')
|
||||
conf.set_override(
|
||||
'api_paste_config',
|
||||
os.path.abspath(
|
||||
'ceilometer/tests/functional/gabbi/gabbi_paste.ini')
|
||||
)
|
||||
|
||||
# A special pipeline is required to use the direct publisher.
|
||||
conf.set_override('pipeline_cfg_file',
|
||||
@ -148,3 +154,24 @@ class EventDataFixture(fixture.GabbiFixture):
|
||||
def stop_fixture(self):
|
||||
"""Destroy the events."""
|
||||
self.conn.db.event.remove({'event_type': '/^cookies_/'})
|
||||
|
||||
|
||||
class CORSConfigFixture(fixture.GabbiFixture):
|
||||
"""Inject mock configuration for the CORS middleware."""
|
||||
|
||||
def start_fixture(self):
|
||||
# Here we monkeypatch GroupAttr.__getattr__, necessary because the
|
||||
# paste.ini method of initializing this middleware creates its own
|
||||
# ConfigOpts instance, bypassing the regular config fixture.
|
||||
|
||||
def _mock_getattr(instance, key):
|
||||
if key != 'allowed_origin':
|
||||
return self._original_call_method(instance, key)
|
||||
return "http://valid.example.com"
|
||||
|
||||
self._original_call_method = cfg.ConfigOpts.GroupAttr.__getattr__
|
||||
cfg.ConfigOpts.GroupAttr.__getattr__ = _mock_getattr
|
||||
|
||||
def stop_fixture(self):
|
||||
"""Remove the monkeypatch."""
|
||||
cfg.ConfigOpts.GroupAttr.__getattr__ = self._original_call_method
|
||||
|
27
ceilometer/tests/functional/gabbi/gabbi_paste.ini
Normal file
27
ceilometer/tests/functional/gabbi/gabbi_paste.ini
Normal file
@ -0,0 +1,27 @@
|
||||
# Ceilometer API WSGI Pipeline
|
||||
# Define the filters that make up the pipeline for processing WSGI requests
|
||||
# Note: This pipeline is PasteDeploy's term rather than Ceilometer's pipeline
|
||||
# used for processing samples
|
||||
#
|
||||
# This version is specific for gabbi. It removes support for keystone while
|
||||
# keeping suport for CORS.
|
||||
|
||||
# Remove authtoken from the pipeline if you don't want to use keystone authentication
|
||||
[pipeline:main]
|
||||
pipeline = cors api-server
|
||||
|
||||
[app:api-server]
|
||||
paste.app_factory = ceilometer.api.app:app_factory
|
||||
|
||||
[filter:authtoken]
|
||||
paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = ceilometer
|
||||
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
|
||||
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
44
ceilometer/tests/functional/gabbi/gabbits/middleware.yaml
Normal file
44
ceilometer/tests/functional/gabbi/gabbits/middleware.yaml
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# Test the middlewares. Just CORS for now.
|
||||
#
|
||||
|
||||
fixtures:
|
||||
- ConfigFixture
|
||||
- CORSConfigFixture
|
||||
|
||||
tests:
|
||||
|
||||
- name: valid cors options
|
||||
OPTIONS: /
|
||||
status: 200
|
||||
request_headers:
|
||||
origin: http://valid.example.com
|
||||
access-control-request-method: GET
|
||||
response_headers:
|
||||
access-control-allow-origin: http://valid.example.com
|
||||
|
||||
- name: invalid cors options
|
||||
OPTIONS: /
|
||||
status: 200
|
||||
request_headers:
|
||||
origin: http://invalid.example.com
|
||||
access-control-request-method: GET
|
||||
response_forbidden_headers:
|
||||
- access-control-allow-origin
|
||||
|
||||
- name: valid cors get
|
||||
GET: /
|
||||
status: 200
|
||||
request_headers:
|
||||
origin: http://valid.example.com
|
||||
access-control-request-method: GET
|
||||
response_headers:
|
||||
access-control-allow-origin: http://valid.example.com
|
||||
|
||||
- name: invalid cors get
|
||||
GET: /
|
||||
status: 200
|
||||
request_headers:
|
||||
origin: http://invalid.example.com
|
||||
response_forbidden_headers:
|
||||
- access-control-allow-origin
|
@ -32,5 +32,5 @@ def load_tests(loader, tests, pattern):
|
||||
"""Provide a TestSuite to the discovery process."""
|
||||
test_dir = os.path.join(os.path.dirname(__file__), TESTS_DIR)
|
||||
return driver.build_tests(test_dir, loader, host=None,
|
||||
intercept=app.setup_app,
|
||||
intercept=app.load_app,
|
||||
fixture_module=fixture_module)
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
# Remove authtoken from the pipeline if you don't want to use keystone authentication
|
||||
[pipeline:main]
|
||||
pipeline = request_id authtoken api-server
|
||||
pipeline = cors request_id authtoken api-server
|
||||
|
||||
[app:api-server]
|
||||
paste.app_factory = ceilometer.api.app:app_factory
|
||||
@ -16,3 +16,9 @@ paste.filter_factory = keystonemiddleware.auth_token:filter_factory
|
||||
[filter:request_id]
|
||||
paste.filter_factory = oslo_middleware:RequestId.factory
|
||||
|
||||
[filter:cors]
|
||||
paste.filter_factory = oslo_middleware.cors:filter_factory
|
||||
oslo_config_project = ceilometer
|
||||
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
|
||||
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
|
@ -6,6 +6,7 @@ namespace = oslo.concurrency
|
||||
namespace = oslo.db
|
||||
namespace = oslo.log
|
||||
namespace = oslo.messaging
|
||||
namespace = oslo.middleware.cors
|
||||
namespace = oslo.policy
|
||||
namespace = oslo.service.service
|
||||
namespace = keystonemiddleware.auth_token
|
||||
|
Loading…
Reference in New Issue
Block a user