diff --git a/CHANGELOG.md b/CHANGELOG.md index 6ddf14e18d..3a589a23d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Changed site URL check to allow protocol mismatches if `INVENTREE_SITE_LAX_PROTOCOL` is set to `True` (default) in [#10454](https://github.com/inventree/InvenTree/pull/10454) + ### Removed diff --git a/docs/docs/start/config.md b/docs/docs/start/config.md index bb1523a3f8..c151bf6a32 100644 --- a/docs/docs/start/config.md +++ b/docs/docs/start/config.md @@ -135,6 +135,7 @@ Depending on how your InvenTree installation is configured, you will need to pay | INVENTREE_CORS_ORIGIN_WHITELIST | cors.whitelist | List of whitelisted CORS URLs. Refer to the [django-cors-headers documentation](https://github.com/adamchainz/django-cors-headers#cors_allowed_origins-sequencestr) | Uses the *INVENTREE_SITE_URL* parameter, if set. Otherwise, an empty list. | | INVENTREE_CORS_ORIGIN_REGEX | cors.regex | List of regular expressions for CORS whitelisted URL patterns | *Empty list* | | INVENTREE_CORS_ALLOW_CREDENTIALS | cors.allow_credentials | Allow cookies in cross-site requests | `True` | +| INVENTREE_SITE_LAX_PROTOCOL | site_lax_protocol | Ignore protocol mismatches on INVE-E7 site checks | `True` | | INVENTREE_USE_X_FORWARDED_HOST | use_x_forwarded_host | Use forwarded host header | `False` | | INVENTREE_USE_X_FORWARDED_PORT | use_x_forwarded_port | Use forwarded port header | `False` | | INVENTREE_USE_X_FORWARDED_PROTO | use_x_forwarded_proto | Use forwarded protocol header | `False` | diff --git a/src/backend/InvenTree/InvenTree/middleware.py b/src/backend/InvenTree/InvenTree/middleware.py index 4bfb0ace37..a886aa3eac 100644 --- a/src/backend/InvenTree/InvenTree/middleware.py +++ b/src/backend/InvenTree/InvenTree/middleware.py @@ -234,9 +234,17 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin): if path in urls or any(path.startswith(p) for p in paths_ignore): return None - # Ensure that the settings are set correctly with the current request + # treat the accessed scheme and host accessed_scheme = request._current_scheme_host - if accessed_scheme and not accessed_scheme.startswith(settings.SITE_URL): + referer = urlsplit(accessed_scheme) + + # Ensure that the settings are set correctly with the current request + matches = ( + (accessed_scheme and not accessed_scheme.startswith(settings.SITE_URL)) + if not settings.SITE_LAX_PROTOCOL_CHECK + else not is_same_domain(referer.netloc, urlsplit(settings.SITE_URL).netloc) + ) + if matches: if ( isinstance(settings.CSRF_TRUSTED_ORIGINS, list) and len(settings.CSRF_TRUSTED_ORIGINS) > 1 @@ -251,7 +259,6 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin): ) # Check trusted origins - referer = urlsplit(accessed_scheme) if not any( is_same_domain(referer.netloc, host) for host in [ diff --git a/src/backend/InvenTree/InvenTree/settings.py b/src/backend/InvenTree/InvenTree/settings.py index e5a3f4297e..25ae289a4c 100644 --- a/src/backend/InvenTree/InvenTree/settings.py +++ b/src/backend/InvenTree/InvenTree/settings.py @@ -1064,6 +1064,9 @@ DATE_INPUT_FORMATS = ['%Y-%m-%d'] # Site URL can be specified statically, or via a run-time setting SITE_URL = get_setting('INVENTREE_SITE_URL', 'site_url', None) +SITE_LAX_PROTOCOL_CHECK = get_boolean_setting( + 'INVENTREE_SITE_LAX_PROTOCOL', 'site_lax_protocol', True +) if SITE_URL: SITE_URL = str(SITE_URL).strip().rstrip('/') diff --git a/src/backend/InvenTree/InvenTree/test_middleware.py b/src/backend/InvenTree/InvenTree/test_middleware.py index f308d0526d..5793d9949d 100644 --- a/src/backend/InvenTree/InvenTree/test_middleware.py +++ b/src/backend/InvenTree/InvenTree/test_middleware.py @@ -110,6 +110,24 @@ class MiddlewareTests(InvenTreeTestCase): response = self.client.get(reverse('web')) self.do_positive_test(response) + def test_site_lax_protocol(self): + """Test that the site URL check is correctly working with/without lax protocol check.""" + # Simple setup with proxy + with self.settings( + SITE_URL='https://testserver', CSRF_TRUSTED_ORIGINS=['https://testserver'] + ): + response = self.client.get(reverse('web')) + self.do_positive_test(response) + + # No worky if strong security + with self.settings( + SITE_URL='https://testserver', + CSRF_TRUSTED_ORIGINS=['https://testserver'], + SITE_LAX_PROTOCOL_CHECK=False, + ): + response = self.client.get(reverse('web')) + self.assertContains(response, 'INVE-E7: The used path', status_code=500) + def test_site_url_checks_multi(self): """Test that the site URL check is correctly working in a multi-site setup.""" # multi-site setup with trusted origins @@ -162,7 +180,6 @@ class MiddlewareTests(InvenTreeTestCase): CSRF_TRUSTED_ORIGINS=['https://example.com'], ): response = self.client.get(reverse('web')) - self.assertEqual(response.status_code, 500) self.assertContains( response, 'is not in the TRUSTED_ORIGINS', status_code=500 ) @@ -176,7 +193,6 @@ class MiddlewareTests(InvenTreeTestCase): CSRF_TRUSTED_ORIGINS=['http://localhost:8000'], ): response = self.client.get(reverse('web')) - self.assertEqual(response.status_code, 500) self.assertContains( response, 'INVE-E7: The used path `http://testserver` ', status_code=500 )