Support CORS
Add the new middleware CORS for Zaqar It only supports for WSGI. Websocket doesn't need this feature. Change-Id: Ifc6d2d1c5dde5152cab6e3aa2f3cf9f207481267 Implements: blueprint support-cors
This commit is contained in:
parent
66e90d3b25
commit
e501f4013e
@ -111,6 +111,11 @@ function configure_zaqar {
|
|||||||
iniset $ZAQAR_CONF DEFAULT pooling True
|
iniset $ZAQAR_CONF DEFAULT pooling True
|
||||||
iniset $ZAQAR_CONF 'pooling:catalog' enable_virtual_pool True
|
iniset $ZAQAR_CONF 'pooling:catalog' enable_virtual_pool True
|
||||||
|
|
||||||
|
if [ "CORS_ENABLED" == 'true'] ; then
|
||||||
|
iniset $ZAQAR_CONF cors
|
||||||
|
iniset $ZAQAR_CONF 'cors' enabled True
|
||||||
|
fi
|
||||||
|
|
||||||
# NOTE(flaper87): Configure mongodb regardless so we can use it as a pool
|
# NOTE(flaper87): Configure mongodb regardless so we can use it as a pool
|
||||||
# in tests.
|
# in tests.
|
||||||
configure_mongodb
|
configure_mongodb
|
||||||
|
@ -45,5 +45,7 @@ ZAQAR_TRUSTEE_DOMAIN=${ZAQAR_TRUSTEE_DOMAIN:-default}
|
|||||||
# Tell Tempest this project is present
|
# Tell Tempest this project is present
|
||||||
TEMPEST_SERVICES+=,zaqar
|
TEMPEST_SERVICES+=,zaqar
|
||||||
|
|
||||||
|
# CORS
|
||||||
|
CORS_ENABLED=${CORS_ENABLED:-false}
|
||||||
|
|
||||||
enable_service zaqar-websocket zaqar-wsgi
|
enable_service zaqar-websocket zaqar-wsgi
|
||||||
|
125
doc/source/CORS.rst
Normal file
125
doc/source/CORS.rst
Normal file
@ -0,0 +1,125 @@
|
|||||||
|
..
|
||||||
|
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.
|
||||||
|
|
||||||
|
==========
|
||||||
|
CORS Guide
|
||||||
|
==========
|
||||||
|
|
||||||
|
Zaqar supports Cross-Origin Resource Sharing (CORS) now. The function is
|
||||||
|
provided by oslo.middleware. Please see `Official Doc`_ and `OpenStack Spec`_
|
||||||
|
for more detail. This guide is mainly tell users how to use it in Zaqar.
|
||||||
|
|
||||||
|
|
||||||
|
New Config Options
|
||||||
|
------------------
|
||||||
|
|
||||||
|
There are some new config options.
|
||||||
|
|
||||||
|
**enabled**
|
||||||
|
|
||||||
|
Enables CORS functions for Zaqar. The default value is "False" at this moment.
|
||||||
|
It will be turn to "True" in the future once it's stable enough.
|
||||||
|
|
||||||
|
**allowed_origin**
|
||||||
|
|
||||||
|
Indicate whether this resource may be shared with the domain received in the
|
||||||
|
requests "origin" header. Format: "<protocol>://<host>[:<port>]", no trailing
|
||||||
|
slash. Example: https://horizon.example.com'.
|
||||||
|
|
||||||
|
**allow_credentials**
|
||||||
|
|
||||||
|
Indicate that the actual request can include user credentials. The default
|
||||||
|
value is True.
|
||||||
|
|
||||||
|
**expose_headers**
|
||||||
|
|
||||||
|
Indicate which headers are safe to expose to the API. Defaults to HTTP Simple
|
||||||
|
Headers. The default value is [].
|
||||||
|
|
||||||
|
**max_age**
|
||||||
|
|
||||||
|
Maximum cache age of CORS preflight requests. The default value is 3600.
|
||||||
|
|
||||||
|
**allow_methods**
|
||||||
|
|
||||||
|
Indicate which methods can be used during the actual request. The default value
|
||||||
|
is ['OPTIONS', 'GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'TRACE', 'PATCH'].
|
||||||
|
|
||||||
|
**allow_headers**
|
||||||
|
|
||||||
|
Indicate which header field names may be used during the actual request. The
|
||||||
|
default value is [].
|
||||||
|
|
||||||
|
|
||||||
|
Request and Response example
|
||||||
|
----------------------------
|
||||||
|
To use CORS, you should make sure that the feature is enabled::
|
||||||
|
|
||||||
|
[cors]
|
||||||
|
enabled = true
|
||||||
|
allowed_origin = http://example
|
||||||
|
allow_methods = GET
|
||||||
|
|
||||||
|
the above example config options mean that Zaqar only receive the GET request
|
||||||
|
from http://example domain. Here are some example request:
|
||||||
|
1. Zaqar will do nothing if the request doesn't contain "Origin" header::
|
||||||
|
|
||||||
|
# curl -I -X GET http://10.229.47.217:8888 -H "Accept: application/json"
|
||||||
|
|
||||||
|
HTTP/1.1 300 Multiple Choices
|
||||||
|
content-length: 668
|
||||||
|
content-type: application/json; charset=UTF-8
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
2. Zaqar will return nothing in response headers if the "Origin" is not in
|
||||||
|
``allowed_origin``::
|
||||||
|
|
||||||
|
# curl -I -X GET http://10.229.47.217:8888 -H "Accept: application/json" -H "Origin: http://"
|
||||||
|
|
||||||
|
HTTP/1.1 300 Multiple Choices
|
||||||
|
content-length: 668
|
||||||
|
content-type: application/json; charset=UTF-8
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
In the Zaqar log, we can see a message::
|
||||||
|
|
||||||
|
CORS request from origin 'http://' not permitted.
|
||||||
|
|
||||||
|
3. Zaqar will return CORS information if the "Origin" header is in
|
||||||
|
``allowed_origin``::
|
||||||
|
|
||||||
|
# curl -I -X GET http://10.229.47.217:8888 -H "Accept: application/json" -H "Origin: http://example"
|
||||||
|
|
||||||
|
HTTP/1.1 300 Multiple Choices
|
||||||
|
content-length: 668
|
||||||
|
content-type: application/json; charset=UTF-8
|
||||||
|
Vary: Origin
|
||||||
|
Access-Control-Allow-Origin: http://example
|
||||||
|
Access-Control-Allow-Credentials: true
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
4. Zaqar will return more information if the request doesn't follow Zaqar's\
|
||||||
|
CORS rule::
|
||||||
|
|
||||||
|
# curl -I -X PUT http://10.229.47.217:8888 -H "Accept: application/json" -H "Origin: http://example"
|
||||||
|
HTTP/1.1 405 Method Not Allowed
|
||||||
|
content-length: 0
|
||||||
|
content-type: application/json; charset=UTF-8
|
||||||
|
allow: GET, OPTIONS
|
||||||
|
Vary: Origin
|
||||||
|
Access-Control-Allow-Origin: http://example
|
||||||
|
Access-Control-Allow-Credentials: true
|
||||||
|
Connection: close
|
||||||
|
|
||||||
|
.. _Official Doc: http://docs.openstack.org/developer/osprofiler/background.html
|
||||||
|
.. _OpenStack Spec: http://specs.openstack.org/openstack/openstack-specs/specs/cors-support.html
|
@ -16,7 +16,7 @@ OSprofiler Guide
|
|||||||
================
|
================
|
||||||
|
|
||||||
OSprofiler is a library from oslo. It's used for performance analysis. Please
|
OSprofiler is a library from oslo. It's used for performance analysis. Please
|
||||||
see `Office Doc`_ for more detail.
|
see `Official Doc`_ for more detail.
|
||||||
|
|
||||||
Preparation
|
Preparation
|
||||||
-----------
|
-----------
|
||||||
@ -121,4 +121,4 @@ Then you can open the file "list_test" to get the result.
|
|||||||
.. note:: If you used MQ for data transfer, the "--connection-string" here
|
.. note:: If you used MQ for data transfer, the "--connection-string" here
|
||||||
could be ignored or set it to your Ceilometer endpoint.
|
could be ignored or set it to your Ceilometer endpoint.
|
||||||
|
|
||||||
.. _Office Doc: http://docs.openstack.org/developer/osprofiler/background.html
|
.. _Official Doc: http://docs.openstack.org/developer/osprofiler/background.html
|
||||||
|
@ -189,6 +189,7 @@ Feature Guide
|
|||||||
|
|
||||||
subscription_confirm
|
subscription_confirm
|
||||||
OSprofiler
|
OSprofiler
|
||||||
|
CORS
|
||||||
|
|
||||||
Other resources
|
Other resources
|
||||||
===============
|
===============
|
||||||
|
@ -15,5 +15,6 @@ namespace = zaqar.transport.validation
|
|||||||
namespace = keystonemiddleware.auth_token
|
namespace = keystonemiddleware.auth_token
|
||||||
namespace = oslo.cache
|
namespace = oslo.cache
|
||||||
namespace = oslo.messaging
|
namespace = oslo.messaging
|
||||||
|
namespace = oslo.middleware.cors
|
||||||
namespace = osprofiler
|
namespace = osprofiler
|
||||||
namespace = oslo.reports
|
namespace = oslo.reports
|
||||||
|
4
releasenotes/notes/support-cors-af8349382a44aa0d.yaml
Normal file
4
releasenotes/notes/support-cors-af8349382a44aa0d.yaml
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
---
|
||||||
|
features:
|
||||||
|
- Zaqar now supports Cross-Origin Resource Sharing (CORS). It turns off by
|
||||||
|
default. Use "enable=True" in [cors] section from zaqar.conf to use it.
|
@ -104,6 +104,7 @@ _NOTIFICATION_OPTIONS = (
|
|||||||
|
|
||||||
_NOTIFICATION_GROUP = 'notification'
|
_NOTIFICATION_GROUP = 'notification'
|
||||||
|
|
||||||
|
|
||||||
_PROFILER_OPTIONS = [
|
_PROFILER_OPTIONS = [
|
||||||
cfg.BoolOpt("trace_wsgi_transport", default=False,
|
cfg.BoolOpt("trace_wsgi_transport", default=False,
|
||||||
help="If False doesn't trace any transport requests."
|
help="If False doesn't trace any transport requests."
|
||||||
@ -117,9 +118,19 @@ _PROFILER_OPTIONS = [
|
|||||||
_PROFILER_GROUP = "profiler"
|
_PROFILER_GROUP = "profiler"
|
||||||
|
|
||||||
|
|
||||||
|
_CORS_OPTIONS = [
|
||||||
|
cfg.BoolOpt("enabled", default=False,
|
||||||
|
help="Whether enable Cross Origin Resource Sharing(CORS) "
|
||||||
|
"function from oslo.middleware"),
|
||||||
|
]
|
||||||
|
|
||||||
|
_CORS_GROUP = "cors"
|
||||||
|
|
||||||
|
|
||||||
def _config_options():
|
def _config_options():
|
||||||
return [(None, _GENERAL_OPTIONS),
|
return [(None, _GENERAL_OPTIONS),
|
||||||
(_DRIVER_GROUP, _DRIVER_OPTIONS),
|
(_DRIVER_GROUP, _DRIVER_OPTIONS),
|
||||||
(_SIGNED_URL_GROUP, _SIGNED_URL_OPTIONS),
|
(_SIGNED_URL_GROUP, _SIGNED_URL_OPTIONS),
|
||||||
(_NOTIFICATION_GROUP, _NOTIFICATION_OPTIONS),
|
(_NOTIFICATION_GROUP, _NOTIFICATION_OPTIONS),
|
||||||
(_PROFILER_GROUP, _PROFILER_OPTIONS)]
|
(_PROFILER_GROUP, _PROFILER_OPTIONS),
|
||||||
|
(_CORS_GROUP, _CORS_OPTIONS)]
|
||||||
|
55
zaqar/transport/middleware/cors.py
Normal file
55
zaqar/transport/middleware/cors.py
Normal file
@ -0,0 +1,55 @@
|
|||||||
|
# Copyright 2017 OpenStack, Inc.
|
||||||
|
# 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.
|
||||||
|
|
||||||
|
from oslo_log import log
|
||||||
|
from oslo_middleware import cors
|
||||||
|
|
||||||
|
LOG = log.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class CORSMiddleware(object):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def install(cls, app, conf):
|
||||||
|
|
||||||
|
LOG.debug(u'Installing CORS middleware.')
|
||||||
|
cors.set_defaults(
|
||||||
|
allow_headers=['X-Auth-Token',
|
||||||
|
'X-Identity-Status',
|
||||||
|
'X-Roles',
|
||||||
|
'X-Service-Catalog',
|
||||||
|
'X-User-Id',
|
||||||
|
'X-Tenant-Id',
|
||||||
|
'X-OpenStack-Request-ID',
|
||||||
|
'X-Trace-Info',
|
||||||
|
'X-Trace-HMAC',
|
||||||
|
'Client-id'],
|
||||||
|
expose_headers=['X-Auth-Token',
|
||||||
|
'X-Subject-Token',
|
||||||
|
'X-Service-Token',
|
||||||
|
'X-OpenStack-Request-ID'],
|
||||||
|
allow_methods=['GET',
|
||||||
|
'PUT',
|
||||||
|
'POST',
|
||||||
|
'DELETE',
|
||||||
|
'PATCH',
|
||||||
|
'HEAD']
|
||||||
|
)
|
||||||
|
|
||||||
|
return cors.CORS(app, conf)
|
||||||
|
|
||||||
|
|
||||||
|
def install_cors(app, conf):
|
||||||
|
return CORSMiddleware.install(app, conf)
|
@ -29,6 +29,7 @@ from zaqar.i18n import _
|
|||||||
from zaqar import transport
|
from zaqar import transport
|
||||||
from zaqar.transport import acl
|
from zaqar.transport import acl
|
||||||
from zaqar.transport.middleware import auth
|
from zaqar.transport.middleware import auth
|
||||||
|
from zaqar.transport.middleware import cors
|
||||||
from zaqar.transport.middleware import profile
|
from zaqar.transport.middleware import profile
|
||||||
from zaqar.transport import validation
|
from zaqar.transport import validation
|
||||||
from zaqar.transport.wsgi import v1_0
|
from zaqar.transport.wsgi import v1_0
|
||||||
@ -153,6 +154,11 @@ class Driver(transport.DriverBase):
|
|||||||
|
|
||||||
self.app = auth.SignedHeadersAuth(self.app, auth_app)
|
self.app = auth.SignedHeadersAuth(self.app, auth_app)
|
||||||
|
|
||||||
|
# NOTE(wangxiyuan): Install CORS, this middleware should be called
|
||||||
|
# before Keystone auth.
|
||||||
|
if self._conf.cors.enabled:
|
||||||
|
self.app = cors.install_cors(self.app, self._conf)
|
||||||
|
|
||||||
acl.setup_policy(self._conf)
|
acl.setup_policy(self._conf)
|
||||||
|
|
||||||
def _error_handler(self, exc, request, response, params):
|
def _error_handler(self, exc, request, response, params):
|
||||||
|
Loading…
Reference in New Issue
Block a user