diff --git a/metadeploy/multitenancy/iprestrict_middleware.py b/metadeploy/multitenancy/iprestrict_middleware.py index 40d1e83c5..7fbc15685 100644 --- a/metadeploy/multitenancy/iprestrict_middleware.py +++ b/metadeploy/multitenancy/iprestrict_middleware.py @@ -2,6 +2,7 @@ from . import current_site_id from django.conf import settings from django.http import HttpResponseForbidden +from ipaddress import ip_network, ip_address ADMIN_URL = f"/{settings.ADMIN_URL}/".replace("//", "/") @@ -23,10 +24,21 @@ def __call__(self, request): ) should_filter = not is_admin_url and has_ip_allowlist - if should_filter and client_ip not in profile.allowed_ip_addresses: + if should_filter and not self.validate_ip(client_ip, profile.allowed_ip_addresses): return HttpResponseForbidden( "You don't have permission to access this resource." ) response = self.get_response(request) return response + + def validate_ip(self, target_ip, allowed_ips): + try: + target_ip_obj = ip_address(target_ip) + for allowed_ip in allowed_ips: + allowed_ip_obj = ip_network(allowed_ip, strict=False) + if target_ip_obj in allowed_ip_obj: + return True + return False + except ValueError: + return False \ No newline at end of file diff --git a/metadeploy/multitenancy/tests/test_iprestrict_middleware.py b/metadeploy/multitenancy/tests/test_iprestrict_middleware.py index fb8687f63..573b41256 100644 --- a/metadeploy/multitenancy/tests/test_iprestrict_middleware.py +++ b/metadeploy/multitenancy/tests/test_iprestrict_middleware.py @@ -3,6 +3,7 @@ from metadeploy.api.models import SiteProfile from django.test import RequestFactory, TestCase from unittest.mock import patch +import json class IPRestrictionMiddlewaretest(TestCase): @@ -14,11 +15,32 @@ def test_ip_restrict_middleware_with_matching_allowed_client_ip(self, mock_site_ request = self.factory.get('/test') request.META["REMOTE_ADDR"] = "127.0.0.1" + allowed_ips = '["127.0.0.2","127.0.0.1"]' + allowed_ip_list = json.loads(allowed_ips) + site = Site.objects.create(name="Test") mock_site_profile = SiteProfile() mock_site_profile.site = site mock_site_profile.name = site.name - mock_site_profile.allowed_ip_addresses = '["127.0.0.1"]' + mock_site_profile.allowed_ip_addresses = allowed_ip_list + mock_site_profile_get.return_value = mock_site_profile + + response = IPRestrictMiddleware(lambda x: x)(request) + assert response == request + + @patch('metadeploy.multitenancy.iprestrict_middleware.IPRestrictMiddleware.getSiteProfile') + def test_ip_restrict_middleware_with_matching_allowed_client_ip_cidr_format(self, mock_site_profile_get): + request = self.factory.get('/test') + request.META["REMOTE_ADDR"] = "127.0.0.1" + + allowed_ips = '["127.0.0.3","127.0.0.2/30"]' + allowed_ip_list = json.loads(allowed_ips) + + site = Site.objects.create(name="Test") + mock_site_profile = SiteProfile() + mock_site_profile.site = site + mock_site_profile.name = site.name + mock_site_profile.allowed_ip_addresses = allowed_ip_list mock_site_profile_get.return_value = mock_site_profile response = IPRestrictMiddleware(lambda x: x)(request)