From 6426a1d177cf0d8aaa5a202a63389c7455c40b39 Mon Sep 17 00:00:00 2001 From: "gcp-cherry-pick-bot[bot]" <98988430+gcp-cherry-pick-bot[bot]@users.noreply.github.com> Date: Fri, 19 Jul 2024 17:19:29 +0200 Subject: [PATCH] core: improve error handling on ASGI level (cherry-pick #10547) (#10552) core: improve error handling on ASGI level (#10547) Signed-off-by: Jens Langhammer Co-authored-by: Jens L. --- authentik/enterprise/providers/rac/urls.py | 2 +- authentik/{core => outposts}/channels.py | 0 authentik/outposts/tests/test_ws.py | 6 ++---- authentik/outposts/urls.py | 2 +- authentik/root/middleware.py | 6 +++++- ...4_squashed_0013_identificationstage_passwordless_flow.py | 2 +- 6 files changed, 10 insertions(+), 8 deletions(-) rename authentik/{core => outposts}/channels.py (100%) diff --git a/authentik/enterprise/providers/rac/urls.py b/authentik/enterprise/providers/rac/urls.py index 8ee5e32089..ddfbcf1152 100644 --- a/authentik/enterprise/providers/rac/urls.py +++ b/authentik/enterprise/providers/rac/urls.py @@ -5,7 +5,6 @@ from channels.sessions import CookieMiddleware from django.urls import path from django.views.decorators.csrf import ensure_csrf_cookie -from authentik.core.channels import TokenOutpostMiddleware from authentik.enterprise.providers.rac.api.connection_tokens import ConnectionTokenViewSet from authentik.enterprise.providers.rac.api.endpoints import EndpointViewSet from authentik.enterprise.providers.rac.api.property_mappings import RACPropertyMappingViewSet @@ -13,6 +12,7 @@ from authentik.enterprise.providers.rac.api.providers import RACProviderViewSet from authentik.enterprise.providers.rac.consumer_client import RACClientConsumer from authentik.enterprise.providers.rac.consumer_outpost import RACOutpostConsumer from authentik.enterprise.providers.rac.views import RACInterface, RACStartView +from authentik.outposts.channels import TokenOutpostMiddleware from authentik.root.asgi_middleware import SessionMiddleware from authentik.root.middleware import ChannelsLoggingMiddleware diff --git a/authentik/core/channels.py b/authentik/outposts/channels.py similarity index 100% rename from authentik/core/channels.py rename to authentik/outposts/channels.py diff --git a/authentik/outposts/tests/test_ws.py b/authentik/outposts/tests/test_ws.py index effb91a84a..7ce50eb799 100644 --- a/authentik/outposts/tests/test_ws.py +++ b/authentik/outposts/tests/test_ws.py @@ -2,7 +2,6 @@ from dataclasses import asdict -from channels.exceptions import DenyConnection from channels.routing import URLRouter from channels.testing import WebsocketCommunicator from django.test import TransactionTestCase @@ -37,9 +36,8 @@ class TestOutpostWS(TransactionTestCase): communicator = WebsocketCommunicator( URLRouter(websocket.websocket_urlpatterns), f"/ws/outpost/{self.outpost.pk}/" ) - with self.assertRaises(DenyConnection): - connected, _ = await communicator.connect() - self.assertFalse(connected) + connected, _ = await communicator.connect() + self.assertFalse(connected) async def test_auth_valid(self): """Test auth with token""" diff --git a/authentik/outposts/urls.py b/authentik/outposts/urls.py index 42bb779241..80ed1156d4 100644 --- a/authentik/outposts/urls.py +++ b/authentik/outposts/urls.py @@ -2,13 +2,13 @@ from django.urls import path -from authentik.core.channels import TokenOutpostMiddleware from authentik.outposts.api.outposts import OutpostViewSet from authentik.outposts.api.service_connections import ( DockerServiceConnectionViewSet, KubernetesServiceConnectionViewSet, ServiceConnectionViewSet, ) +from authentik.outposts.channels import TokenOutpostMiddleware from authentik.outposts.consumer import OutpostConsumer from authentik.root.middleware import ChannelsLoggingMiddleware diff --git a/authentik/root/middleware.py b/authentik/root/middleware.py index 39eb3b1257..017dee60c6 100644 --- a/authentik/root/middleware.py +++ b/authentik/root/middleware.py @@ -274,9 +274,13 @@ class ChannelsLoggingMiddleware: self.log(scope) try: return await self.inner(scope, receive, send) + except DenyConnection: + return await send({"type": "websocket.close"}) except Exception as exc: + if settings.DEBUG: + raise exc LOGGER.warning("Exception in ASGI application", exc=exc) - raise DenyConnection() from None + return await send({"type": "websocket.close"}) def log(self, scope: dict, **kwargs): """Log request""" diff --git a/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py b/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py index e1cc14d4eb..3154c4d058 100644 --- a/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py +++ b/authentik/stages/identification/migrations/0002_auto_20200530_2204_squashed_0013_identificationstage_passwordless_flow.py @@ -144,7 +144,7 @@ class Migration(migrations.Migration): default=None, help_text=( "When set, shows a password field, instead of showing the password field as" - " seaprate step." + " separate step." ), null=True, on_delete=django.db.models.deletion.SET_NULL,