From e1c8961a7c7d2602ee3c28adc60b2d1f2f0a2a94 Mon Sep 17 00:00:00 2001 From: Takashi Kajinami Date: Mon, 8 Sep 2025 22:11:48 +0900 Subject: [PATCH] Fix missing CORS middleware CORS middleware needs to be added to api pipeline to support Cross-Origin Resource Sharing(CORS). CORS is supported globally by multiple OpenStack services but is not by watcher, due to lack of CORS middleware and no mechanism to inject it into api pipeline. Closes-Bug: #2122347 Change-Id: I6b47abe4f08dc257e9156b254fa60005b82898d7 Signed-off-by: Takashi Kajinami --- .../oslo-config-generator/watcher.conf | 1 + releasenotes/notes/cors-e506801ebc0ed3f1.yaml | 6 +++++ setup.cfg | 3 +++ watcher/api/app.py | 8 +++++++ watcher/common/config.py | 22 +++++++++++++++++++ watcher/common/service.py | 1 + 6 files changed, 41 insertions(+) create mode 100644 releasenotes/notes/cors-e506801ebc0ed3f1.yaml diff --git a/etc/watcher/oslo-config-generator/watcher.conf b/etc/watcher/oslo-config-generator/watcher.conf index 5474c575a..c3a34f823 100644 --- a/etc/watcher/oslo-config-generator/watcher.conf +++ b/etc/watcher/oslo-config-generator/watcher.conf @@ -9,6 +9,7 @@ namespace = oslo.concurrency namespace = oslo.db namespace = oslo.log namespace = oslo.messaging +namespace = oslo.middleware.cors namespace = oslo.middleware.http_proxy_to_wsgi namespace = oslo.policy namespace = oslo.reports diff --git a/releasenotes/notes/cors-e506801ebc0ed3f1.yaml b/releasenotes/notes/cors-e506801ebc0ed3f1.yaml new file mode 100644 index 000000000..e4e72c8fe --- /dev/null +++ b/releasenotes/notes/cors-e506801ebc0ed3f1.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + The `CORS middleware + `__ + has been added to api pipeline, to support Cross-Origin Resource Sharing. diff --git a/setup.cfg b/setup.cfg index b3886e895..dbe9909c8 100644 --- a/setup.cfg +++ b/setup.cfg @@ -35,6 +35,9 @@ monasca = oslo.config.opts = watcher = watcher.conf.opts:list_opts +oslo.config.opts.defaults = + watcher = watcher.common.config:set_lib_defaults + oslo.policy.policies = watcher = watcher.common.policies:list_rules diff --git a/watcher/api/app.py b/watcher/api/app.py index bc5c65758..3e125adce 100644 --- a/watcher/api/app.py +++ b/watcher/api/app.py @@ -17,6 +17,7 @@ # under the License. +from oslo_middleware import cors from oslo_middleware import http_proxy_to_wsgi from oslo_middleware import request_id import pecan @@ -59,6 +60,13 @@ def _wrap_app(app): app = http_proxy_to_wsgi.HTTPProxyToWSGI(app) + # 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, CONF) + return app diff --git a/watcher/common/config.py b/watcher/common/config.py index ce70ae40b..413b16768 100644 --- a/watcher/common/config.py +++ b/watcher/common/config.py @@ -16,11 +16,33 @@ # under the License. from oslo_config import cfg +from oslo_middleware import cors from watcher.common import rpc from watcher import version +def set_lib_defaults(): + 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'], + expose_headers=['X-Auth-Token', + 'X-Subject-Token', + 'X-Service-Token', + 'X-OpenStack-Request-ID'], + allow_methods=['GET', + 'PUT', + 'POST', + 'DELETE', + 'PATCH'] + ) + + def parse_args(argv, default_config_files=None, default_config_dirs=None): default_config_files = (default_config_files or cfg.find_config_files(project='watcher')) diff --git a/watcher/common/service.py b/watcher/common/service.py index 8dbc9627f..49f009369 100644 --- a/watcher/common/service.py +++ b/watcher/common/service.py @@ -281,6 +281,7 @@ def prepare_service(argv=(), conf=cfg.CONF): config.parse_args(argv) cfg.set_defaults(_options.log_opts, default_log_levels=_DEFAULT_LOG_LEVELS) + config.set_lib_defaults() log.setup(conf, 'python-watcher') conf.log_opt_values(LOG, log.DEBUG) objects.register_all()