Skip to content

Commit 2c18ec8

Browse files
AAP-47499 Use get_settings to get CSRF_TRUSTED_ORIGINS in ansible_base SessionAuthentication (#755)
## Description - What is being changed? Modify ansible_base.authentication.session.SessionAuthentication to temporarily patch CSRF_TRUSTED_ORIGINS with the setting retrieved from `ansible_base.lib.utils.settings.get_setting` - Why is this change needed? To support dynamic definitions of the CSRF_TRUSTED_ORIGIN setting, provided the correct ANSIBLE_BASE_SETTINGS_FUNCTION - How does this change address the issue? By having SessionAuthentication temporarily patch CSRF_TRUSTED_ORIGINS for the duration of csrf enforcement ## Type of Change <!-- Mandatory: Check one or more boxes that apply --> - [ ] Bug fix (non-breaking change which fixes an issue) - [X] New feature (non-breaking change which adds functionality) - [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) - [ ] Documentation update - [X] Test update - [ ] Refactoring (no functional changes) - [ ] Development environment change - [ ] Configuration change ## Self-Review Checklist <!-- These items help ensure quality - they complement our automated CI checks --> - [ ] I have performed a self-review of my code - [ ] I have added relevant comments to complex code sections - [ ] I have updated documentation where needed - [ ] I have considered the security impact of these changes - [ ] I have considered performance implications - [ ] I have thought about error handling and edge cases - [ ] I have tested the changes in my local environment ## Testing Instructions ### Prerequisites Run your django app with one worker for simplicity (we cannot guarantee this in testing situations, so this is only for manual verification) ### Steps to Test 1. Modify your ANSIBLE_BASE_SETTINGS_FUNCTION to return a different CSRF_TRUSTED_ORIGINS 2. Make a curl POST request, changing your `Origin` header to match an element of your alternate CSRF_TRUSTED_ORIGINS ### Expected Results - CSRF_TRUSTED_ORIGINS django setting remains unchanged - CSRF origin checking does not fail --------- Co-authored-by: Hao Liu <[email protected]>
1 parent 2fc242f commit 2c18ec8

File tree

3 files changed

+34
-1
lines changed

3 files changed

+34
-1
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,23 @@
11
from rest_framework import authentication
22

3+
from ansible_base.lib.utils.settings import replace_trusted_origins
4+
35

46
class SessionAuthentication(authentication.SessionAuthentication):
57
"""
68
This class allows us to fail with a 401 if the user is not authenticated.
9+
10+
Allows CSRF_TRUSTED_ORIGINS to be read dynamically using get_setting.
11+
Reverting the value of CSRF_TRUSTED_ORIGINS afterwards.
712
"""
813

914
def authenticate_header(self, request):
1015
return "Session"
16+
17+
@replace_trusted_origins
18+
def enforce_csrf(self, request):
19+
"""
20+
Enforce CSRF validation for session based authentication using
21+
AnsibleBaseCsrfViewMiddleware instead of Django's CsrfViewMiddleware.
22+
"""
23+
return super().enforce_csrf(request)

ansible_base/lib/utils/settings.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,24 @@ def get_function_from_setting(setting_name: str) -> Any:
4949
return None
5050

5151

52+
def replace_trusted_origins(func):
53+
"""Decorator for patching the CSRF_TRUSTED_ORIGINS django setting using the potentially different value in get_setting for the duration of a
54+
function call
55+
"""
56+
57+
def override_setting(*args, **kwargs):
58+
csrf_trusted_origins = settings.CSRF_TRUSTED_ORIGINS
59+
try:
60+
# Temporarily patch the setting
61+
settings.CSRF_TRUSTED_ORIGINS = get_setting("CSRF_TRUSTED_ORIGINS", csrf_trusted_origins)
62+
return func(*args, **kwargs)
63+
finally:
64+
# Revert setting after this is done
65+
settings.CSRF_TRUSTED_ORIGINS = csrf_trusted_origins
66+
67+
return override_setting
68+
69+
5270
def get_from_import(module_name, attr):
5371
"Thin wrapper around importlib.import_module, mostly exists so that we can safely mock this in tests"
5472
module = importlib.import_module(module_name, package=attr)

test_app/tests/authentication/test_middleware.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
from django.conf import settings
22
from social_core.exceptions import AuthException
33

4-
from ansible_base.authentication.middleware import SocialExceptionHandlerMiddleware
4+
from ansible_base.authentication.middleware import (
5+
SocialExceptionHandlerMiddleware,
6+
)
57

68

79
def test_social_exception_handler_mw():

0 commit comments

Comments
 (0)