From 05f4a64aeda5f8a75f204754ba6dea7f83d59cf9 Mon Sep 17 00:00:00 2001 From: Michael Krotscheck Date: Wed, 6 May 2015 12:05:24 -0700 Subject: [PATCH] Added CORS support middleware to Ironic This adds the CORS support middleware to Ironic, allowing a deployer to optionally configure rules under which a javascript client may break the single-origin policy and access the API directly. OpenStack Spec: https://review.openstack.org/#/c/179866/ Oslo_Middleware Docs: http://docs.openstack.org/developer/oslo.middleware/cors.html OpenStack Cloud Admin Guide Documentation: http://docs.openstack.org/admin-guide-cloud/cross_project_cors.html Co-Authored-By: Devananda van der Veen Depends-on: I2deed897f8f9ef87e4a74227c4fcea9afdb151e8 Change-Id: Ic55305607e44069d893baf2a261d5fe7da777303 --- etc/ironic/ironic.conf.sample | 62 +++++++++++++++++++++++++++ ironic/api/app.py | 11 +++++ requirements.txt | 1 + tools/config/oslo.config.generator.rc | 2 +- vagrant.yaml | 13 +++++- 5 files changed, 87 insertions(+), 2 deletions(-) diff --git a/etc/ironic/ironic.conf.sample b/etc/ironic/ironic.conf.sample index d50dfcf98a..a60675de7d 100644 --- a/etc/ironic/ironic.conf.sample +++ b/etc/ironic/ironic.conf.sample @@ -598,6 +598,68 @@ #subprocess_timeout=10 +[cors] + +# +# Options defined in oslo.middleware.cors +# + +# Indicate whether this resource may be shared with the domain +# received in the requests "origin" header. (string value) +#allowed_origin= + +# Indicate that the actual request can include user +# credentials (boolean value) +#allow_credentials=true + +# Indicate which headers are safe to expose to the API. +# Defaults to HTTP Simple Headers. (list value) +#expose_headers=Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma + +# Maximum cache age of CORS preflight requests. (integer +# value) +#max_age=3600 + +# Indicate which methods can be used during the actual +# request. (list value) +#allow_methods=GET,POST,PUT,DELETE,OPTIONS + +# Indicate which header field names may be used during the +# actual request. (list value) +#allow_headers=Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma + + +[cors.subdomain] + +# +# Options defined in oslo.middleware.cors +# + +# Indicate whether this resource may be shared with the domain +# received in the requests "origin" header. (string value) +#allowed_origin= + +# Indicate that the actual request can include user +# credentials (boolean value) +#allow_credentials=true + +# Indicate which headers are safe to expose to the API. +# Defaults to HTTP Simple Headers. (list value) +#expose_headers=Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma + +# Maximum cache age of CORS preflight requests. (integer +# value) +#max_age=3600 + +# Indicate which methods can be used during the actual +# request. (list value) +#allow_methods=GET,POST,PUT,DELETE,OPTIONS + +# Indicate which header field names may be used during the +# actual request. (list value) +#allow_headers=Content-Type,Cache-Control,Content-Language,Expires,Last-Modified,Pragma + + [database] # diff --git a/ironic/api/app.py b/ironic/api/app.py index 4307c6aaeb..a9e57ba362 100644 --- a/ironic/api/app.py +++ b/ironic/api/app.py @@ -16,10 +16,12 @@ # under the License. from oslo_config import cfg +import oslo_middleware.cors as cors_middleware import pecan from ironic.api import acl from ironic.api import config +from ironic.api.controllers.base import Version from ironic.api import hooks from ironic.api import middleware from ironic.common.i18n import _ @@ -73,6 +75,15 @@ def setup_app(pecan_config=None, extra_hooks=None): wrap_app=middleware.ParsableErrorMiddleware, ) + # Create a CORS wrapper, and attach ironic-specific defaults that must be + # included in all CORS responses. + app = cors_middleware.CORS(app, CONF) + app.set_latent( + allow_headers=[Version.max_string, Version.min_string, Version.string], + allow_methods=['GET', 'PUT', 'POST', 'DELETE', 'PATCH'], + expose_headers=[Version.max_string, Version.min_string, Version.string] + ) + if pecan_config.app.enable_acl: return acl.install(app, cfg.CONF, pecan_config.app.acl_public_routes) diff --git a/requirements.txt b/requirements.txt index e21b0e5571..7b63287d71 100644 --- a/requirements.txt +++ b/requirements.txt @@ -27,6 +27,7 @@ oslo.db>=2.4.1 # Apache-2.0 oslo.rootwrap>=2.0.0 # Apache-2.0 oslo.i18n>=1.5.0 # Apache-2.0 oslo.log>=1.8.0 # Apache-2.0 +oslo.middleware>=2.8.0 # Apache-2.0 oslo.policy>=0.5.0 # Apache-2.0 oslo.serialization>=1.4.0 # Apache-2.0 oslo.service>=0.7.0 # Apache-2.0 diff --git a/tools/config/oslo.config.generator.rc b/tools/config/oslo.config.generator.rc index e85578e3a6..2b977e866d 100644 --- a/tools/config/oslo.config.generator.rc +++ b/tools/config/oslo.config.generator.rc @@ -1,2 +1,2 @@ -export IRONIC_CONFIG_GENERATOR_EXTRA_LIBRARIES='oslo.db oslo.messaging keystonemiddleware.auth_token oslo.concurrency oslo.policy oslo.log oslo.service.service oslo.service.periodic_task' +export IRONIC_CONFIG_GENERATOR_EXTRA_LIBRARIES='oslo.db oslo.messaging oslo.middleware.cors keystonemiddleware.auth_token oslo.concurrency oslo.policy oslo.log oslo.service.service oslo.service.periodic_task' export IRONIC_CONFIG_GENERATOR_EXTRA_MODULES= diff --git a/vagrant.yaml b/vagrant.yaml index 0d227a4fef..055a4a9dc6 100644 --- a/vagrant.yaml +++ b/vagrant.yaml @@ -124,6 +124,14 @@ section: 'DEFAULT', option: 'pecan_debug', value: 'true' } + - { + section: 'DEFAULT', + option: 'verbose', value: 'true' + } + - { + section: 'DEFAULT', + option: 'debug', value: 'true' + } - { section: 'oslo_messaging_rabbit', option: 'rabbit_host', value: "{{ip}}" @@ -136,7 +144,10 @@ section: 'oslo_messaging_rabbit', option: 'rabbit_password', value: "ironic" } - + - { # CORS Domain For Ironic-Webclient's dev server. + section: 'cors', + option: 'allowed_origin', value: "http://localhost:8000" + } ############################################################################# # Handlers