From 3541ec467c448db1353eca3d595475f6196018f5 Mon Sep 17 00:00:00 2001 From: "Jens L." Date: Fri, 2 Aug 2024 13:50:14 +0200 Subject: [PATCH] sources/scim: fix duplicate service account users and changing token (#10735) Signed-off-by: Jens Langhammer --- authentik/sources/scim/models.py | 3 --- authentik/sources/scim/signals.py | 45 ++++++++++++++++--------------- 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/authentik/sources/scim/models.py b/authentik/sources/scim/models.py index 8bc753077c58..43101b09866f 100644 --- a/authentik/sources/scim/models.py +++ b/authentik/sources/scim/models.py @@ -1,7 +1,6 @@ """SCIM Source""" from typing import Any -from uuid import uuid4 from django.db import models from django.templatetags.static import static @@ -20,8 +19,6 @@ class SCIMSource(Source): @property def service_account_identifier(self) -> str: - if not self.pk: - self.pk = uuid4() return f"ak-source-scim-{self.pk}" @property diff --git a/authentik/sources/scim/signals.py b/authentik/sources/scim/signals.py index 8136a421a014..1875f7382842 100644 --- a/authentik/sources/scim/signals.py +++ b/authentik/sources/scim/signals.py @@ -1,41 +1,44 @@ from django.db.models import Model -from django.db.models.signals import pre_delete, pre_save +from django.db.models.signals import post_delete, post_save from django.dispatch import receiver from authentik.core.models import USER_PATH_SYSTEM_PREFIX, Token, TokenIntents, User, UserTypes +from authentik.events.middleware import audit_ignore from authentik.sources.scim.models import SCIMSource USER_PATH_SOURCE_SCIM = USER_PATH_SYSTEM_PREFIX + "/sources/scim" -@receiver(pre_save, sender=SCIMSource) -def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_): +@receiver(post_save, sender=SCIMSource) +def scim_source_post_save(sender: type[Model], instance: SCIMSource, created: bool, **_): """Create service account before source is saved""" - # .service_account_identifier will auto-assign a primary key uuid to the source - # if none is set yet, just so we can get the identifier before we save identifier = instance.service_account_identifier - user = User.objects.create( + user, _ = User.objects.update_or_create( username=identifier, - name=f"SCIM Source {instance.name} Service-Account", - type=UserTypes.INTERNAL_SERVICE_ACCOUNT, - path=USER_PATH_SOURCE_SCIM, + defaults={ + "name": f"SCIM Source {instance.name} Service-Account", + "type": UserTypes.INTERNAL_SERVICE_ACCOUNT, + "path": USER_PATH_SOURCE_SCIM, + }, ) - token = Token.objects.create( - user=user, + token, token_created = Token.objects.update_or_create( identifier=identifier, - intent=TokenIntents.INTENT_API, - expiring=False, - managed=f"goauthentik.io/sources/scim/{instance.pk}", + defaults={ + "user": user, + "intent": TokenIntents.INTENT_API, + "expiring": False, + "managed": f"goauthentik.io/sources/scim/{instance.pk}", + }, ) - instance.token = token + if created or token_created: + with audit_ignore(): + instance.token = token + instance.save() -@receiver(pre_delete, sender=SCIMSource) -def scim_source_pre_delete(sender: type[Model], instance: SCIMSource, **_): - """Delete SCIM Source service account before deleting source""" - Token.objects.filter( - identifier=instance.service_account_identifier, intent=TokenIntents.INTENT_API - ).delete() +@receiver(post_delete, sender=SCIMSource) +def scim_source_post_delete(sender: type[Model], instance: SCIMSource, **_): + """Delete SCIM Source service account after deleting source""" User.objects.filter( username=instance.service_account_identifier, type=UserTypes.INTERNAL_SERVICE_ACCOUNT ).delete()