From 15bf813b0457ac20231d7d3d8ba16347ff605253 Mon Sep 17 00:00:00 2001 From: Dariusz Niemczyk Date: Fri, 25 Aug 2023 21:06:01 +0200 Subject: [PATCH] django: force auth for all requests --- spejstore/settings.py | 1 + storage/authentication.py | 39 +++++++++++++++++++++------------------ storage/middleware.py | 24 ++++++++++++++++++++++++ 3 files changed, 46 insertions(+), 18 deletions(-) create mode 100644 storage/middleware.py diff --git a/spejstore/settings.py b/spejstore/settings.py index 460d662..e1a1090 100644 --- a/spejstore/settings.py +++ b/spejstore/settings.py @@ -63,6 +63,7 @@ MIDDLEWARE = [ "django.middleware.security.SecurityMiddleware", "whitenoise.middleware.WhiteNoiseMiddleware", "django.middleware.cache.UpdateCacheMiddleware", + "storage.middleware.is_authorized_or_in_lan_middleware", "django.middleware.gzip.GZipMiddleware", "django.contrib.sessions.middleware.SessionMiddleware", "django.middleware.common.CommonMiddleware", diff --git a/storage/authentication.py b/storage/authentication.py index 959f071..ec2c262 100644 --- a/storage/authentication.py +++ b/storage/authentication.py @@ -24,7 +24,7 @@ headers_to_check_for_ip = [ def get_request_meta(request, key): - value = request.META.get(key, request).strip() + value = request.META.get(key, "") if value == "": return None return value @@ -40,6 +40,26 @@ def get_ip_from_request(request): return None +def has_permission(request): + if PROD: + client_ip = get_ip_from_request(request) + if client_ip is None: + # This should only happen on localhost env when fiddling with code. + # It's technically impossible to get there with proper headers. + raise exceptions.AuthenticationFailed("Unauthorized: no ip detected?") + # Make sure that we need to check PROXY_TRUSTED_IPS here + if len(PROXY_TRUSTED_IPS) > 0: + if request.META["REMOTE_ADDR"] not in PROXY_TRUSTED_IPS: + raise exceptions.AuthenticationFailed( + "Unauthorized: request is not coming from the PROXY_TRUSTED_IPS machine" + ) + return ipaddress.IPv4Address(client_ip) in ipaddress.IPv4Network( + LAN_ALLOWED_ADDRESS_SPACE + ) + else: + return True + + class LanAuthentication(SessionAuthentication): def authenticate(self, request): is_session_authorized = super().authenticate(request) @@ -56,20 +76,3 @@ class LanAuthentication(SessionAuthentication): def authenticate_header(self, request): return LAN_ALLOWED_HEADER - - def has_permission(self, request): - if PROD: - client_ip = get_ip_from_request(request) - if client_ip is None: - raise exceptions.AuthenticationFailed("Unauthorized: no ip detected?") - # Make sure that we need to check PROXY_TRUSTED_IPS here - if len(PROXY_TRUSTED_IPS) > 0: - if request.META["REMOTE_ADDR"] not in PROXY_TRUSTED_IPS: - raise exceptions.AuthenticationFailed( - "Unauthorized: request is not coming from the PROXY_TRUSTED_IPS machine" - ) - return ipaddress.IPv4Address(client_ip) in ipaddress.IPv4Network( - LAN_ALLOWED_ADDRESS_SPACE - ) - else: - return True diff --git a/storage/middleware.py b/storage/middleware.py new file mode 100644 index 0000000..13dc9d7 --- /dev/null +++ b/storage/middleware.py @@ -0,0 +1,24 @@ +from django.core.exceptions import PermissionDenied +from storage.authentication import has_permission + + +def is_authorized_or_in_lan_middleware(get_response): + # One-time configuration and initialization. + + def middleware(request): + # Code to be executed for each request before + # the view (and later middleware) are called. + + response = get_response(request) + if request.user.is_authenticated: + return response + is_within_lan = has_permission(request) + if is_within_lan: + return response + else: + raise PermissionDenied() + + # Code to be executed for each request/response after + # the view is called. + + return middleware