mirror of
https://github.com/inventree/InvenTree.git
synced 2025-10-03 15:52:51 +00:00
fix(backend): better siteurl testing in middleware (#10335)
* fix(backend): simplify siteurl testing * add multi-site test * pass off site_url check if more than one trusted origin is set * split up testing * add temporary debug info * fix test enviorment
This commit is contained in:
@@ -237,11 +237,18 @@ class InvenTreeHostSettingsMiddleware(MiddlewareMixin):
|
|||||||
# Ensure that the settings are set correctly with the current request
|
# Ensure that the settings are set correctly with the current request
|
||||||
accessed_scheme = request._current_scheme_host
|
accessed_scheme = request._current_scheme_host
|
||||||
if accessed_scheme and not accessed_scheme.startswith(settings.SITE_URL):
|
if accessed_scheme and not accessed_scheme.startswith(settings.SITE_URL):
|
||||||
msg = f'INVE-E7: The used path `{accessed_scheme}` does not match the SITE_URL `{settings.SITE_URL}`'
|
if (
|
||||||
logger.error(msg)
|
isinstance(settings.CSRF_TRUSTED_ORIGINS, list)
|
||||||
return render(
|
and len(settings.CSRF_TRUSTED_ORIGINS) > 1
|
||||||
request, 'config_error.html', {'error_message': msg}, status=500
|
):
|
||||||
)
|
# The used url might not be the primary url - next check determines if in a trusted origins
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
msg = f'INVE-E7: The used path `{accessed_scheme}` does not match the SITE_URL `{settings.SITE_URL}`'
|
||||||
|
logger.error(msg)
|
||||||
|
return render(
|
||||||
|
request, 'config_error.html', {'error_message': msg}, status=500
|
||||||
|
)
|
||||||
|
|
||||||
# Check trusted origins
|
# Check trusted origins
|
||||||
referer = urlsplit(accessed_scheme)
|
referer = urlsplit(accessed_scheme)
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
"""Tests for middleware functions."""
|
"""Tests for middleware functions."""
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from django.urls import reverse
|
from django.urls import reverse
|
||||||
|
|
||||||
@@ -87,36 +88,72 @@ class MiddlewareTests(InvenTreeTestCase):
|
|||||||
log_error('testpath')
|
log_error('testpath')
|
||||||
check(1)
|
check(1)
|
||||||
|
|
||||||
|
def do_positive_test(self, response):
|
||||||
|
"""Helper function to check for positive test results."""
|
||||||
|
self.assertEqual(response.status_code, 200)
|
||||||
|
self.assertNotContains(response, 'INVE-E7')
|
||||||
|
self.assertContains(response, 'window.INVENTREE_SETTINGS')
|
||||||
|
|
||||||
def test_site_url_checks(self):
|
def test_site_url_checks(self):
|
||||||
"""Test that the site URL check is correctly working."""
|
"""Test that the site URL check is correctly working."""
|
||||||
# correctly set
|
# simple setup
|
||||||
with self.settings(
|
with self.settings(
|
||||||
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://testserver']
|
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://testserver']
|
||||||
):
|
):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.do_positive_test(response)
|
||||||
self.assertNotContains(response, 'INVE-E7')
|
|
||||||
self.assertContains(response, 'window.INVENTREE_SETTINGS')
|
|
||||||
|
|
||||||
# wrongly set site URL
|
# simple setup with wildcard
|
||||||
with self.settings(SITE_URL='https://example.com'):
|
with self.settings(
|
||||||
|
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://*.testserver']
|
||||||
|
):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 500)
|
self.do_positive_test(response)
|
||||||
self.assertContains(
|
|
||||||
response,
|
|
||||||
'INVE-E7: The used path `http://testserver` does not match',
|
|
||||||
status_code=500,
|
|
||||||
)
|
|
||||||
self.assertNotContains(
|
|
||||||
response, 'window.INVENTREE_SETTINGS', 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
|
||||||
|
with self.settings(
|
||||||
|
SITE_URL='https://testserver.example.com',
|
||||||
|
CSRF_TRUSTED_ORIGINS=[
|
||||||
|
'http://testserver',
|
||||||
|
'https://testserver.example.com',
|
||||||
|
],
|
||||||
|
):
|
||||||
|
# this will run with testserver as host by default
|
||||||
|
response = self.client.get(reverse('web'))
|
||||||
|
self.do_positive_test(response)
|
||||||
|
|
||||||
|
# Now test with the "outside" url name
|
||||||
|
response = self.client.get(
|
||||||
|
'https://testserver.example.com/web/',
|
||||||
|
SERVER_NAME='testserver.example.com',
|
||||||
|
)
|
||||||
|
self.do_positive_test(response)
|
||||||
|
|
||||||
|
# A non-trsuted origin must still fail in multi - origin setup
|
||||||
|
response = self.client.get(
|
||||||
|
'https://not-my-testserver.example.com/web/',
|
||||||
|
SERVER_NAME='not-my-testserver.example.com',
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 500)
|
||||||
|
|
||||||
|
# Even if it is a subdomain
|
||||||
|
response = self.client.get(
|
||||||
|
'https://not-my.testserver.example.com/web/',
|
||||||
|
SERVER_NAME='not-my.testserver.example.com',
|
||||||
|
)
|
||||||
|
self.assertEqual(response.status_code, 500)
|
||||||
|
|
||||||
|
def test_site_url_checks_fails(self):
|
||||||
|
"""Test that the site URL check is correctly failing.
|
||||||
|
|
||||||
|
Important for security.
|
||||||
|
"""
|
||||||
# wrongly set but in debug -> is ignored
|
# wrongly set but in debug -> is ignored
|
||||||
with self.settings(SITE_URL='https://example.com', DEBUG=True):
|
with self.settings(SITE_URL='https://example.com', DEBUG=True):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.do_positive_test(response)
|
||||||
self.assertNotContains(response, 'INVE-E7')
|
|
||||||
self.assertContains(response, 'window.INVENTREE_SETTINGS')
|
|
||||||
|
|
||||||
# wrongly set cors
|
# wrongly set cors
|
||||||
with self.settings(
|
with self.settings(
|
||||||
@@ -133,10 +170,32 @@ class MiddlewareTests(InvenTreeTestCase):
|
|||||||
response, 'window.INVENTREE_SETTINGS', status_code=500
|
response, 'window.INVENTREE_SETTINGS', status_code=500
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# wrongly set site URL
|
||||||
with self.settings(
|
with self.settings(
|
||||||
SITE_URL='http://testserver', CSRF_TRUSTED_ORIGINS=['http://*.testserver']
|
SITE_URL='https://example.com',
|
||||||
|
CSRF_TRUSTED_ORIGINS=['http://localhost:8000'],
|
||||||
):
|
):
|
||||||
response = self.client.get(reverse('web'))
|
response = self.client.get(reverse('web'))
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 500)
|
||||||
self.assertNotContains(response, 'INVE-E7')
|
self.assertContains(
|
||||||
self.assertContains(response, 'window.INVENTREE_SETTINGS')
|
response, 'INVE-E7: The used path `http://testserver` ', status_code=500
|
||||||
|
)
|
||||||
|
self.assertNotContains(
|
||||||
|
response, 'window.INVENTREE_SETTINGS', status_code=500
|
||||||
|
)
|
||||||
|
|
||||||
|
# Log stuff # TODO remove
|
||||||
|
print(
|
||||||
|
'###DBG-TST###',
|
||||||
|
'site',
|
||||||
|
settings.SITE_URL,
|
||||||
|
'trusted',
|
||||||
|
settings.CSRF_TRUSTED_ORIGINS,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Check that the correct step triggers the error message
|
||||||
|
self.assertContains(
|
||||||
|
response,
|
||||||
|
'INVE-E7: The used path `http://testserver` does not match',
|
||||||
|
status_code=500,
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user