From 6728160ae28e112216d97ed6d468944c21486bc0 Mon Sep 17 00:00:00 2001 From: Vladyslav Drok Date: Wed, 7 Oct 2020 13:45:50 +0200 Subject: [PATCH] Add possibility to configure application root SCRIPT_NAME should be used to correctly construct the returned links. This patch also adds ProxyFix from werkzeug to allow using inspector behind SSL terminating proxy while still keeping the links correct. Change-Id: I4f40e9266a55d237f7aa68324b11f59b667cc940 --- ironic_inspector/main.py | 16 +++++++++++++--- ironic_inspector/test/unit/test_main.py | 14 ++++++++++++++ ...d-proxy-headers-support-127f99f5ff87f03f.yaml | 12 ++++++++++++ 3 files changed, 39 insertions(+), 3 deletions(-) create mode 100644 releasenotes/notes/add-proxy-headers-support-127f99f5ff87f03f.yaml diff --git a/ironic_inspector/main.py b/ironic_inspector/main.py index edb282438..3cca57d31 100644 --- a/ironic_inspector/main.py +++ b/ironic_inspector/main.py @@ -19,6 +19,7 @@ import re import flask from oslo_utils import strutils from oslo_utils import uuidutils +from werkzeug.middleware import proxy_fix from ironic_inspector import api_tools from ironic_inspector.common import context @@ -54,8 +55,14 @@ def _init_middleware(): :returns: None """ - # ensure original root app is restored before wrapping it - _app.wsgi_app = _wsgi_app + # Ensure original root app is restored and wrap it with ProxyFix, + # respecting only the last entry in each header if it contains a list of + # values. The following headers are respected: X-Forwarded-For, + # X-Forwarded-Proto, X-Forwarded-Host, X-Forwarded-Port, + # X-Forwarded-Prefix (the last one sets SCRIPT_NAME environment variable + # that is used to construct links). + _app.wsgi_app = proxy_fix.ProxyFix( + _wsgi_app, x_for=1, x_proto=1, x_host=1, x_port=1, x_prefix=1) if CONF.auth_strategy == 'keystone': utils.add_auth_middleware(_app) elif CONF.auth_strategy == 'http_basic': @@ -206,7 +213,10 @@ def create_link_object(urls): for url in urls: links.append({ "rel": "self", - "href": os.path.join(flask.request.url_root, url).rstrip('/')}) + "href": os.path.join( + os.path.join(flask.request.url_root, + os.environ.get('SCRIPT_NAME', '/').lstrip('/')), + url).rstrip('/')}) return links diff --git a/ironic_inspector/test/unit/test_main.py b/ironic_inspector/test/unit/test_main.py index 4bed53d61..d8021ef83 100644 --- a/ironic_inspector/test/unit/test_main.py +++ b/ironic_inspector/test/unit/test_main.py @@ -65,6 +65,20 @@ class BaseAPITest(test_base.BaseTest): class TestApiIntrospect(BaseAPITest): + def test_root_endpoint_with_prefix(self): + res = self.app.get( + '/', headers={'X-Forwarded-Proto': 'https', + 'X-Forwarded-Host': 'myhost', + 'X-Forwarded-Prefix': '/ironic_inspector'}) + + self.assertEqual(200, res.status_code) + self.assertEqual('application/json', + res.headers['content-type']) + cur_version = res.json['versions'][0] + hrefs = [link['href'] for link in cur_version['links']] + for href in hrefs: + self.assertTrue(href.startswith('https://myhost/ironic_inspector')) + def test_introspect(self): res = self.app.post('/v1/introspection/%s' % self.uuid, diff --git a/releasenotes/notes/add-proxy-headers-support-127f99f5ff87f03f.yaml b/releasenotes/notes/add-proxy-headers-support-127f99f5ff87f03f.yaml new file mode 100644 index 000000000..38ddc69f8 --- /dev/null +++ b/releasenotes/notes/add-proxy-headers-support-127f99f5ff87f03f.yaml @@ -0,0 +1,12 @@ +--- +features: + - | + Adds a possibility to setup ironic inspector behind a proxy, while + allowing the links of the resources API returns to remain correct. + Inspector now respects the following headers that are passed with + API requests: ``X-Forwarded-For``, ``X-Forwarded-Proto``, + ``X-Forwarded-Host``, ``X-Forwarded-Port``, ``X-Forwarded-Prefix``. + If the API is run providing ``SCRIPT_NAME`` environment variable, + it is now also respected, and it allows to return the correct links + in response to requests, even if inspector API is not placed at the + web server root resource.