Added CORS support to Keystone

This adds the CORS support middleware to Keystone, allowing a deployer
to optionally configure rules under which a javascript client may
break the single-origin policy and access the API directly.

For keystone the paste.ini method of deploying the middleware was
chosen, because it needs to be able to annotate error responses
created by other middlewares. If one such middleware throws an
error - such as an error from sizelimit - that error response
must still have CORS headers in order to be readable by the
user agent.

This patch also includes tests to assert that the expected setup
entry points are present. It is expected that this test will be
refined in future patches.

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: I151e0ee5da1bf3d9fbbe8f11bb06e687b284e5f6
This commit is contained in:
Michael Krotscheck 2015-11-30 16:09:51 -08:00
parent ed2ff17290
commit 55b056fa9e
2 changed files with 60 additions and 5 deletions

View File

@ -18,6 +18,13 @@ use = egg:keystone#admin_token_auth
[filter:json_body]
use = egg:keystone#json_body
[filter:cors]
use = egg:oslo.middleware#cors
oslo_config_project = keystone
latent_allow_headers = X-Auth-Token, X-Openstack-Request-Id, X-Subject-Token
latent_expose_headers = X-Auth-Token, X-Openstack-Request-Id, X-Subject-Token
latent_allow_methods = GET, PUT, POST, DELETE, PATCH
[filter:ec2_extension]
use = egg:keystone#ec2_extension
@ -45,17 +52,17 @@ use = egg:keystone#admin_service
[pipeline:public_api]
# The last item in this pipeline must be public_service or an equivalent
# application. It cannot be a filter.
pipeline = sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension public_service
pipeline = cors sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension public_service
[pipeline:admin_api]
# The last item in this pipeline must be admin_service or an equivalent
# application. It cannot be a filter.
pipeline = sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension s3_extension admin_service
pipeline = cors sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension s3_extension admin_service
[pipeline:api_v3]
# The last item in this pipeline must be service_v3 or an equivalent
# application. It cannot be a filter.
pipeline = sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension_v3 s3_extension service_v3
pipeline = cors sizelimit url_normalize request_id build_auth_context token_auth admin_token_auth json_body ec2_extension_v3 s3_extension service_v3
[app:public_version_service]
use = egg:keystone#public_version_service
@ -64,10 +71,10 @@ use = egg:keystone#public_version_service
use = egg:keystone#admin_version_service
[pipeline:public_version_api]
pipeline = sizelimit url_normalize public_version_service
pipeline = cors sizelimit url_normalize public_version_service
[pipeline:admin_version_api]
pipeline = sizelimit url_normalize admin_version_service
pipeline = cors sizelimit url_normalize admin_version_service
[composite:main]
use = egg:Paste#urlmap

View File

@ -0,0 +1,48 @@
# 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 stevedore
from testtools import matchers
from keystone.tests.unit import core as test
class TestPasteDeploymentEntryPoints(test.TestCase):
def test_entry_point_middleware(self):
"""Assert that our list of expected middleware is present."""
expected_names = [
'admin_token_auth',
'build_auth_context',
'crud_extension',
'cors',
'debug',
'endpoint_filter_extension',
'ec2_extension',
'ec2_extension_v3',
'federation_extension',
'json_body',
'oauth1_extension',
'request_id',
'revoke_extension',
's3_extension',
'simple_cert_extension',
'sizelimit',
'token_auth',
'url_normalize',
'user_crud_extension',
]
em = stevedore.ExtensionManager('paste.filter_factory')
actual_names = [extension.name for extension in em]
self.assertThat(actual_names, matchers.ContainsAll(expected_names))