diff --git a/mistral/api/app.py b/mistral/api/app.py index 052f5b078..5761f2445 100644 --- a/mistral/api/app.py +++ b/mistral/api/app.py @@ -15,6 +15,7 @@ # limitations under the License. from oslo_config import cfg +import oslo_middleware.cors as cors_middleware import pecan from mistral.api import access_control @@ -62,4 +63,17 @@ def setup_app(config=None): # Set up access control. app = access_control.setup(app) + # Create a CORS wrapper, and attach mistral-specific defaults that must be + # included in all CORS responses. + app = cors_middleware.CORS(app, cfg.CONF) + app.set_latent( + allow_headers=['X-Auth-Token', 'X-Identity-Status', 'X-Roles', + 'X-Service-Catalog', 'X-User-Id', 'X-Tenant-Id' + 'X-Project-Id', 'X-User-Name', 'X-Project-Name'], + allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'], + expose_headers=['X-Auth-Token', 'X-Subject-Token', + 'X-Service-Token', 'X-Project-Id', 'X-User-Name', + 'X-Project-Name'] + ) + return app diff --git a/mistral/tests/unit/api/test_cors_middleware.py b/mistral/tests/unit/api/test_cors_middleware.py new file mode 100644 index 000000000..a2450cdec --- /dev/null +++ b/mistral/tests/unit/api/test_cors_middleware.py @@ -0,0 +1,96 @@ +# All Rights Reserved. +# +# 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. + +"""Tests cors middleware.""" + +from mistral.tests.unit.api import base +from oslo_config import cfg as cfg +from oslo_middleware import cors as cors_middleware + + +class TestCORSMiddleware(base.FunctionalTest): + '''Provide a basic smoke test to ensure CORS middleware is active. + + The tests below provide minimal confirmation that the CORS middleware + is active, and may be configured. For comprehensive tests, please consult + the test suite in oslo_middleware. + ''' + + def setUp(self): + # Make sure the CORS options are registered + cfg.CONF.register_opts(cors_middleware.CORS_OPTS, 'cors') + + # Load up our valid domain values before the application is created. + cfg.CONF.set_override( + "allowed_origin", + "http://valid.example.com", + group='cors' + ) + + # Create the application. + super(TestCORSMiddleware, self).setUp() + + def test_valid_cors_options_request(self): + response = self.app.options( + '/', + headers={ + 'Origin': 'http://valid.example.com', + 'Access-Control-Request-Method': 'GET' + } + ) + + self.assertEqual(200, response.status_code) + self.assertIn('access-control-allow-origin', response.headers) + self.assertEqual( + 'http://valid.example.com', + response.headers['access-control-allow-origin'] + ) + + def test_invalid_cors_options_request(self): + response = self.app.options( + '/', + headers={ + 'Origin': 'http://invalid.example.com', + 'Access-Control-Request-Method': 'GET' + } + ) + + self.assertEqual(200, response.status_code) + self.assertNotIn('access-control-allow-origin', response.headers) + + def test_valid_cors_get_request(self): + response = self.app.get( + '/', + headers={ + 'Origin': 'http://valid.example.com' + } + ) + + self.assertEqual(200, response.status_code) + self.assertIn('access-control-allow-origin', response.headers) + self.assertEqual( + 'http://valid.example.com', + response.headers['access-control-allow-origin'] + ) + + def test_invalid_cors_get_request(self): + response = self.app.get( + '/', + headers={ + 'Origin': 'http://invalid.example.com' + } + ) + + self.assertEqual(200, response.status_code) + self.assertNotIn('access-control-allow-origin', response.headers) diff --git a/requirements.txt b/requirements.txt index 4ed35b14f..a0006304c 100644 --- a/requirements.txt +++ b/requirements.txt @@ -14,6 +14,7 @@ oslo.concurrency>=2.3.0 # Apache-2.0 oslo.config>=3.2.0 # Apache-2.0 oslo.db>=4.1.0 # Apache-2.0 oslo.messaging>=4.0.0 # Apache-2.0 +oslo.middleware>=3.0.0 # Apache-2.0 oslo.utils>=3.4.0 # Apache-2.0 oslo.log>=1.14.0 # Apache-2.0 oslo.serialization>=1.10.0 # Apache-2.0 diff --git a/tools/config/config-generator.mistral.conf b/tools/config/config-generator.mistral.conf index 93f32fb93..40734c09f 100644 --- a/tools/config/config-generator.mistral.conf +++ b/tools/config/config-generator.mistral.conf @@ -2,6 +2,7 @@ namespace = mistral.config namespace = oslo.db namespace = oslo.messaging +namespace = oslo.middleware.cors namespace = keystonemiddleware.auth_token namespace = periodic.config namespace = oslo.log \ No newline at end of file