From 7f65b06033afca20399305f285ff5e6d43c5131c Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Mon, 19 Oct 2015 06:52:04 -0700 Subject: [PATCH] Added CORS support to Neutron This adds the CORS support middleware to Neutron, allowing a deployer to optionally configure rules under which a javascript client may break the single-origin policy and access the API directly. For neutron, both the paste.ini and the direct-wrap method of deploying the middleware were chosen, since neutron is in a state of migration to pecan. Note that if someone deploys pecan-neutron behind other middleware, any responses provided by that middleware will not be CORS-enabled, as these responses would be returned before the headers could be annotated. This results in a response not readable by the user agent. 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 DocImpact: Add link to CORS configuration in admin cloud guide. Change-Id: I02acea6124d28370d92e7c94ca2d1d6c5c8937ac --- etc/api-paste.ini | 11 +++++++++-- etc/oslo-config-generator/neutron.conf | 1 + neutron/pecan_wsgi/app.py | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 2 deletions(-) diff --git a/etc/api-paste.ini b/etc/api-paste.ini index 4fb3ddbae..3e79feb9e 100644 --- a/etc/api-paste.ini +++ b/etc/api-paste.ini @@ -5,8 +5,8 @@ use = egg:Paste#urlmap [composite:neutronapi_v2_0] use = call:neutron.auth:pipeline_factory -noauth = request_id catch_errors extensions neutronapiapp_v2_0 -keystone = request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0 +noauth = cors request_id catch_errors extensions neutronapiapp_v2_0 +keystone = cors request_id catch_errors authtoken keystonecontext extensions neutronapiapp_v2_0 [filter:request_id] paste.filter_factory = oslo_middleware:RequestId.factory @@ -14,6 +14,13 @@ paste.filter_factory = oslo_middleware:RequestId.factory [filter:catch_errors] paste.filter_factory = oslo_middleware:CatchErrors.factory +[filter:cors] +paste.filter_factory = oslo_middleware.cors:filter_factory +oslo_config_project = neutron +latent_allow_headers = X-Auth-Token, X-Openstack-Request-Id +latent_expose_headers = X-Auth-Token, X-Openstack-Request-Id +latent_allow_methods = GET, PUT, POST, DELETE, PATCH + [filter:keystonecontext] paste.filter_factory = neutron.auth:NeutronKeystoneContext.factory diff --git a/etc/oslo-config-generator/neutron.conf b/etc/oslo-config-generator/neutron.conf index f55a562ec..1d61c360b 100644 --- a/etc/oslo-config-generator/neutron.conf +++ b/etc/oslo-config-generator/neutron.conf @@ -13,6 +13,7 @@ namespace = oslo.db namespace = oslo.policy namespace = oslo.concurrency namespace = oslo.messaging +namespace = oslo.middleware.cors namespace = oslo.service.sslutils namespace = oslo.service.wsgi namespace = keystonemiddleware.auth_token diff --git a/neutron/pecan_wsgi/app.py b/neutron/pecan_wsgi/app.py index 77d4c44a2..7860da5a7 100644 --- a/neutron/pecan_wsgi/app.py +++ b/neutron/pecan_wsgi/app.py @@ -15,6 +15,7 @@ from keystonemiddleware import auth_token from oslo_config import cfg +from oslo_middleware import cors from oslo_middleware import request_id import pecan @@ -74,4 +75,17 @@ def _wrap_app(app): else: raise n_exc.InvalidConfigurationOption( opt_name='auth_strategy', opt_value=cfg.CONF.auth_strategy) + + # This should be the last middleware in the list (which results in + # it being the first in the middleware chain). This is to ensure + # that any errors thrown by other middleware, such as an auth + # middleware - are annotated with CORS headers, and thus accessible + # by the browser. + app = cors.CORS(app, cfg.CONF) + app.set_latent( + allow_headers=['X-Auth-Token', 'X-Openstack-Request-Id'], + allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'], + expose_headers=['X-Auth-Token', 'X-Openstack-Request-Id'] + ) + return app -- 2.45.2