Skip to content

Commit

Permalink
Trust proxy headers for host provision callback
Browse files Browse the repository at this point in the history
* Do not remove special header list if request is from a trusted proxy.
* Continue to remove headers if request if from a non-trusted proxy.
  • Loading branch information
chrismeyersfsu committed Jun 7, 2024
1 parent 8827ae7 commit 8cab2ab
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 16 deletions.
30 changes: 20 additions & 10 deletions awx/api/generics.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
from ansible_base.lib.utils.requests import get_remote_host
from ansible_base.rbac.models import RoleEvaluation, RoleDefinition
from ansible_base.rbac.permission_registry import permission_registry
from ansible_base.jwt_consumer.common.util import validate_x_trusted_proxy_header

# AWX
from awx.main.models import UnifiedJob, UnifiedJobTemplate, User, Role, Credential, WorkflowJobTemplateNode, WorkflowApprovalTemplate
Expand Down Expand Up @@ -153,22 +154,31 @@ def initialize_request(self, request, *args, **kwargs):
Store the Django REST Framework Request object as an attribute on the
normal Django request, store time the request started.
"""
is_trusted_proxy = False

self.time_started = time.time()
if getattr(settings, 'SQL_DEBUG', False):
self.queries_before = len(connection.queries)

if 'HTTP_X_TRUSTED_PROXY' in request.META:
if validate_x_trusted_proxy_header(request.META['HTTP_X_TRUSTED_PROXY']):
is_trusted_proxy = True
else:
logger.warning("Request appeared to be a trusted upstream proxy but failed to provide a matching shared secret.")

# If there are any custom headers in REMOTE_HOST_HEADERS, make sure
# they respect the allowed proxy list
if all(
[
settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_ALLOWED_LIST,
]
):
for custom_header in settings.REMOTE_HOST_HEADERS:
if custom_header.startswith('HTTP_'):
request.environ.pop(custom_header, None)
if not is_trusted_proxy:
if all(
[
settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_ADDR') not in settings.PROXY_IP_ALLOWED_LIST,
request.environ.get('REMOTE_HOST') not in settings.PROXY_IP_ALLOWED_LIST,
]
):
for custom_header in settings.REMOTE_HOST_HEADERS:
if custom_header.startswith('HTTP_'):
request.environ.pop(custom_header, None)

drf_request = super(APIView, self).initialize_request(request, *args, **kwargs)
request.drf_request = drf_request
Expand Down
9 changes: 3 additions & 6 deletions awx/api/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
from wsgiref.util import FileWrapper

# django-ansible-base
from ansible_base.lib.utils.requests import get_remote_hosts
from ansible_base.rbac.models import RoleEvaluation, ObjectRole
from ansible_base.resource_registry.shared_types import OrganizationType, TeamType, UserType

Expand Down Expand Up @@ -2770,12 +2771,8 @@ def find_matching_hosts(self):
host for the current request.
"""
# Find the list of remote host names/IPs to check.
remote_hosts = set()
for header in settings.REMOTE_HOST_HEADERS:
for value in self.request.META.get(header, '').split(','):
value = value.strip()
if value:
remote_hosts.add(value)

remote_hosts = set(get_remote_hosts(self.request))
# Add the reverse lookup of IP addresses.
for rh in list(remote_hosts):
try:
Expand Down

0 comments on commit 8cab2ab

Please sign in to comment.