events: fix race condition (#10602)

Signed-off-by: Jens Langhammer <jens@goauthentik.io>
This commit is contained in:
Jens L.
2024-07-24 16:49:02 +02:00
committed by GitHub
parent 4101168552
commit 49a2a3ba05
3 changed files with 14 additions and 1 deletions

View File

@ -35,6 +35,7 @@ IGNORED_MODELS = tuple(
_CTX_OVERWRITE_USER = ContextVar[User | None]("authentik_events_log_overwrite_user", default=None)
_CTX_IGNORE = ContextVar[bool]("authentik_events_log_ignore", default=False)
_CTX_REQUEST = ContextVar[HttpRequest | None]("authentik_events_log_request", default=None)
def should_log_model(model: Model) -> bool:
@ -149,11 +150,13 @@ class AuditMiddleware:
m2m_changed.disconnect(dispatch_uid=request.request_id)
def __call__(self, request: HttpRequest) -> HttpResponse:
_CTX_REQUEST.set(request)
self.connect(request)
response = self.get_response(request)
self.disconnect(request)
_CTX_REQUEST.set(None)
return response
def process_exception(self, request: HttpRequest, exception: Exception):
@ -167,7 +170,7 @@ class AuditMiddleware:
thread = EventNewThread(
EventAction.SUSPICIOUS_REQUEST,
request,
message=str(exception),
message=exception_to_string(exception),
)
thread.run()
elif before_send({}, {"exc_info": (None, exception, None)}) is not None:
@ -192,6 +195,8 @@ class AuditMiddleware:
return
if _CTX_IGNORE.get():
return
if request.request_id != _CTX_REQUEST.get().request_id:
return
user = self.get_user(request)
action = EventAction.MODEL_CREATED if created else EventAction.MODEL_UPDATED
@ -205,6 +210,8 @@ class AuditMiddleware:
return
if _CTX_IGNORE.get():
return
if request.request_id != _CTX_REQUEST.get().request_id:
return
user = self.get_user(request)
EventNewThread(
@ -230,6 +237,8 @@ class AuditMiddleware:
return
if _CTX_IGNORE.get():
return
if request.request_id != _CTX_REQUEST.get().request_id:
return
user = self.get_user(request)
EventNewThread(

View File

@ -238,6 +238,8 @@ class Event(SerializerModel, ExpiringModel):
"args": cleanse_dict(QueryDict(request.META.get("QUERY_STRING", ""))),
"user_agent": request.META.get("HTTP_USER_AGENT", ""),
}
if hasattr(request, "request_id"):
self.context["http_request"]["request_id"] = request.request_id
# Special case for events created during flow execution
# since they keep the http query within a wrapped query
if QS_QUERY in self.context["http_request"]["args"]:

View File

@ -8,6 +8,7 @@ from django.urls import reverse
from rest_framework.exceptions import ValidationError
from authentik.brands.utils import get_brand_for_request
from authentik.core.middleware import RESPONSE_HEADER_ID
from authentik.core.tests.utils import create_test_admin_user, create_test_flow
from authentik.events.models import Event, EventAction
from authentik.flows.models import FlowDesignation, FlowStageBinding
@ -186,6 +187,7 @@ class AuthenticatorValidateStageDuoTests(FlowTestCase):
"method": "GET",
"path": f"/api/v3/flows/executor/{flow.slug}/",
"user_agent": "",
"request_id": response[RESPONSE_HEADER_ID],
},
},
)