mirror of
https://github.com/inventree/InvenTree.git
synced 2025-10-03 15:52:51 +00:00
feat(backend): releax protocol check (#10454)
* feat(backend): releax protocol check * add changelog entry * fix variable name --------- Co-authored-by: Oliver <oliver.henry.walters@gmail.com>
This commit is contained in:
@@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Changed
|
### 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
|
### Removed
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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_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_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_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_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_PORT | use_x_forwarded_port | Use forwarded port header | `False` |
|
||||||
| INVENTREE_USE_X_FORWARDED_PROTO | use_x_forwarded_proto | Use forwarded protocol header | `False` |
|
| INVENTREE_USE_X_FORWARDED_PROTO | use_x_forwarded_proto | Use forwarded protocol header | `False` |
|
||||||
|
@@ -234,9 +234,17 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin):
|
|||||||
if path in urls or any(path.startswith(p) for p in paths_ignore):
|
if path in urls or any(path.startswith(p) for p in paths_ignore):
|
||||||
return None
|
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
|
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 (
|
if (
|
||||||
isinstance(settings.CSRF_TRUSTED_ORIGINS, list)
|
isinstance(settings.CSRF_TRUSTED_ORIGINS, list)
|
||||||
and len(settings.CSRF_TRUSTED_ORIGINS) > 1
|
and len(settings.CSRF_TRUSTED_ORIGINS) > 1
|
||||||
@@ -251,7 +259,6 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin):
|
|||||||
)
|
)
|
||||||
|
|
||||||
# Check trusted origins
|
# Check trusted origins
|
||||||
referer = urlsplit(accessed_scheme)
|
|
||||||
if not any(
|
if not any(
|
||||||
is_same_domain(referer.netloc, host)
|
is_same_domain(referer.netloc, host)
|
||||||
for host in [
|
for host in [
|
||||||
|
@@ -1064,6 +1064,9 @@ DATE_INPUT_FORMATS = ['%Y-%m-%d']
|
|||||||
|
|
||||||
# Site URL can be specified statically, or via a run-time setting
|
# Site URL can be specified statically, or via a run-time setting
|
||||||
SITE_URL = get_setting('INVENTREE_SITE_URL', 'site_url', None)
|
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:
|
if SITE_URL:
|
||||||
SITE_URL = str(SITE_URL).strip().rstrip('/')
|
SITE_URL = str(SITE_URL).strip().rstrip('/')
|
||||||
|
@@ -110,6 +110,24 @@ class MiddlewareTests(InvenTreeTestCase):
|
|||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.do_positive_test(response)
|
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):
|
def test_site_url_checks_multi(self):
|
||||||
"""Test that the site URL check is correctly working in a multi-site setup."""
|
"""Test that the site URL check is correctly working in a multi-site setup."""
|
||||||
# multi-site setup with trusted origins
|
# multi-site setup with trusted origins
|
||||||
@@ -162,7 +180,6 @@ class MiddlewareTests(InvenTreeTestCase):
|
|||||||
CSRF_TRUSTED_ORIGINS=['https://example.com'],
|
CSRF_TRUSTED_ORIGINS=['https://example.com'],
|
||||||
):
|
):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 500)
|
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
response, 'is not in the TRUSTED_ORIGINS', status_code=500
|
response, 'is not in the TRUSTED_ORIGINS', status_code=500
|
||||||
)
|
)
|
||||||
@@ -176,7 +193,6 @@ class MiddlewareTests(InvenTreeTestCase):
|
|||||||
CSRF_TRUSTED_ORIGINS=['http://localhost:8000'],
|
CSRF_TRUSTED_ORIGINS=['http://localhost:8000'],
|
||||||
):
|
):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 500)
|
|
||||||
self.assertContains(
|
self.assertContains(
|
||||||
response, 'INVE-E7: The used path `http://testserver` ', status_code=500
|
response, 'INVE-E7: The used path `http://testserver` ', status_code=500
|
||||||
)
|
)
|
||||||
|
Reference in New Issue
Block a user