def validate_auth_user(headers: HttpHeaders, gateway_config: "GatewayConfig") -> bool: username = gateway_config.connection_params["webhook_user"] password = gateway_config.connection_params["webhook_user_password"] auth_header: Optional[str] = headers.get("Authorization") if not auth_header and not username: return True if auth_header and not username: return False if not auth_header and username: return False split_auth = auth_header.split(maxsplit=1) # type: ignore prefix = "BASIC" if len(split_auth) != 2 or split_auth[0].upper() != prefix: return False auth = split_auth[1] try: decoded_auth = base64.b64decode(auth).decode() request_username, request_password = decoded_auth.split(":") user_is_correct = request_username == username if user_is_correct and check_password(request_password, password): return True except binascii.Error: pass return False
def mirror_request_to_elasticsearch(request: Union[HttpRequest, Request]): """ Duplicate request and send-again against this server, with the ES header attached to mirror non-elasticsearch load against elasticsearch for load testing """ url = request.build_absolute_uri() data = json.dumps(request.data) headers = { **request.headers, HttpHeaders.parse_header_name(EXPERIMENTAL_API_HEADER): ELASTICSEARCH_HEADER_VALUE, } logger.warning( "Mirroring inbound request with elasticsearch experimental header.") # NOTE: Purposely desiring an immediate timeout, with ignoring of that timeout error, # since this is a fire-and-forget way to siphon off duplicate load-testing traffic to the server, # without disrupting the primary request try: if request.method == "GET": requests.get(url, data, headers=headers, timeout=0.01) elif request.method == "POST": requests.post(url, data, headers=headers, timeout=0.01) else: pass # TODO: Preemptive timeout still seems to cause the request to be recorded as 500 with: # ConnectionResetError: [Errno 54] Connection reset by peer. # See if this can be avoided in a different way than forcing an early timeout except (requests.exceptions.Timeout, ConnectionResetError): pass except Exception as exc: logger.exception("Mirrored request using Elasticsearch failed", exc_info=exc)
def test_parse_header_name(self): tests = ( ('PATH_INFO', None), ('HTTP_ACCEPT', 'Accept'), ('HTTP_USER_AGENT', 'User-Agent'), ('HTTP_X_FORWARDED_PROTO', 'X-Forwarded-Proto'), ('CONTENT_TYPE', 'Content-Type'), ('CONTENT_LENGTH', 'Content-Length'), ) for header, expected in tests: with self.subTest(header=header): self.assertEqual(HttpHeaders.parse_header_name(header), expected)
def test_basic(self): environ = { 'CONTENT_TYPE': 'text/html', 'CONTENT_LENGTH': '100', 'HTTP_HOST': 'example.com', } headers = HttpHeaders(environ) self.assertEqual(sorted(headers), ['Content-Length', 'Content-Type', 'Host']) self.assertEqual(headers, { 'Content-Type': 'text/html', 'Content-Length': '100', 'Host': 'example.com', })
def test_parse_header_name(self): tests = ( ("PATH_INFO", None), ("HTTP_ACCEPT", "Accept"), ("HTTP_USER_AGENT", "User-Agent"), ("HTTP_X_FORWARDED_PROTO", "X-Forwarded-Proto"), ("CONTENT_TYPE", "Content-Type"), ("CONTENT_LENGTH", "Content-Length"), ) for header, expected in tests: with self.subTest(header=header): self.assertEqual(HttpHeaders.parse_header_name(header), expected)
def _build_request( self, method: str, path: str, data: Dict, request_params: Any ) -> Mock: request = Mock() request.method = method request.path = path request.body = "" request.COOKIES = {} request._dont_enforce_csrf_checks = True request.is_secure.return_value = False request.build_absolute_uri = build_absolute_uri if "user" not in request_params: request.user.is_authenticated = False request.META = request_params.pop("META", {}) request.FILES = request_params.pop("FILES", {}) request.META.update( dict( [ (f"HTTP_{k.replace('-', '_')}", v) for k, v in request_params.pop("headers", {}).items() ] ) ) if django.VERSION[:2] > (2, 1): from django.http.request import HttpHeaders request.headers = HttpHeaders(request.META) if isinstance(data, QueryDict): request.POST = data else: request.POST = QueryDict(mutable=True) for k, v in data.items(): request.POST[k] = v if "?" in path: request.GET = QueryDict(path.split("?")[1]) else: request.GET = QueryDict() for k, v in request_params.items(): setattr(request, k, v) return request
def test_basic(self): environ = { "CONTENT_TYPE": "text/html", "CONTENT_LENGTH": "100", "HTTP_HOST": "example.com", } headers = HttpHeaders(environ) self.assertEqual(sorted(headers), ["Content-Length", "Content-Type", "Host"]) self.assertEqual( headers, { "Content-Type": "text/html", "Content-Length": "100", "Host": "example.com", }, )
def _build_request(self, method: str, path: str, data: dict, request_params: dict): request = Mock() request.method = method request.path = path request.body = "" request.COOKIES = {} if "user" not in request_params: request.user.is_authenticated = False request.META = request_params.pop("META", {}) request.META.update( dict([(f"HTTP_{k}", v) for k, v in request_params.pop("headers", {}).items()])) if django.VERSION[:2] > (2, 1): from django.http.request import HttpHeaders request.headers = HttpHeaders(request.META) if isinstance(data, QueryDict): request.POST = data else: request.POST = QueryDict(mutable=True) for k, v in data.items(): request.POST[k] = v if "?" in path: request.GET = QueryDict(path.split("?")[1]) else: request.GET = QueryDict() for k, v in request_params.items(): setattr(request, k, v) return request
def _bad_token_message(self, reason, token_source): if token_source != 'POST': # Assume it is a settings.CSRF_HEADER_NAME value. header_name = HttpHeaders.parse_header_name(token_source) token_source = f'the {header_name!r} HTTP header' return f'CSRF token from {token_source} {reason}.'