sources/scim: fix duplicate service account users and changing token (#10735) Signed-off-by: Jens Langhammer <jens@goauthentik.io> Co-authored-by: Jens L. <jens@goauthentik.io>
This commit is contained in:
		
				
					committed by
					
						
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							fe7662f80d
						
					
				
				
					commit
					fb9aa9d7f7
				
			@ -1,7 +1,5 @@
 | 
				
			|||||||
"""SCIM Source"""
 | 
					"""SCIM Source"""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from uuid import uuid4
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from django.db import models
 | 
					from django.db import models
 | 
				
			||||||
from django.templatetags.static import static
 | 
					from django.templatetags.static import static
 | 
				
			||||||
from django.utils.translation import gettext_lazy as _
 | 
					from django.utils.translation import gettext_lazy as _
 | 
				
			||||||
@ -19,8 +17,6 @@ class SCIMSource(Source):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def service_account_identifier(self) -> str:
 | 
					    def service_account_identifier(self) -> str:
 | 
				
			||||||
        if not self.pk:
 | 
					 | 
				
			||||||
            self.pk = uuid4()
 | 
					 | 
				
			||||||
        return f"ak-source-scim-{self.pk}"
 | 
					        return f"ak-source-scim-{self.pk}"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
 | 
				
			|||||||
@ -1,41 +1,44 @@
 | 
				
			|||||||
from django.db.models import Model
 | 
					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 django.dispatch import receiver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from authentik.core.models import USER_PATH_SYSTEM_PREFIX, Token, TokenIntents, User, UserTypes
 | 
					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
 | 
					from authentik.sources.scim.models import SCIMSource
 | 
				
			||||||
 | 
					
 | 
				
			||||||
USER_PATH_SOURCE_SCIM = USER_PATH_SYSTEM_PREFIX + "/sources/scim"
 | 
					USER_PATH_SOURCE_SCIM = USER_PATH_SYSTEM_PREFIX + "/sources/scim"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@receiver(pre_save, sender=SCIMSource)
 | 
					@receiver(post_save, sender=SCIMSource)
 | 
				
			||||||
def scim_source_pre_save(sender: type[Model], instance: SCIMSource, **_):
 | 
					def scim_source_post_save(sender: type[Model], instance: SCIMSource, created: bool, **_):
 | 
				
			||||||
    """Create service account before source is saved"""
 | 
					    """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
 | 
					    identifier = instance.service_account_identifier
 | 
				
			||||||
    user = User.objects.create(
 | 
					    user, _ = User.objects.update_or_create(
 | 
				
			||||||
        username=identifier,
 | 
					        username=identifier,
 | 
				
			||||||
        name=f"SCIM Source {instance.name} Service-Account",
 | 
					        defaults={
 | 
				
			||||||
        type=UserTypes.INTERNAL_SERVICE_ACCOUNT,
 | 
					            "name": f"SCIM Source {instance.name} Service-Account",
 | 
				
			||||||
        path=USER_PATH_SOURCE_SCIM,
 | 
					            "type": UserTypes.INTERNAL_SERVICE_ACCOUNT,
 | 
				
			||||||
 | 
					            "path": USER_PATH_SOURCE_SCIM,
 | 
				
			||||||
 | 
					        },
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
    token = Token.objects.create(
 | 
					    token, token_created = Token.objects.update_or_create(
 | 
				
			||||||
        user=user,
 | 
					 | 
				
			||||||
        identifier=identifier,
 | 
					        identifier=identifier,
 | 
				
			||||||
        intent=TokenIntents.INTENT_API,
 | 
					        defaults={
 | 
				
			||||||
        expiring=False,
 | 
					            "user": user,
 | 
				
			||||||
        managed=f"goauthentik.io/sources/scim/{instance.pk}",
 | 
					            "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)
 | 
					@receiver(post_delete, sender=SCIMSource)
 | 
				
			||||||
def scim_source_pre_delete(sender: type[Model], instance: SCIMSource, **_):
 | 
					def scim_source_post_delete(sender: type[Model], instance: SCIMSource, **_):
 | 
				
			||||||
    """Delete SCIM Source service account before deleting source"""
 | 
					    """Delete SCIM Source service account after deleting source"""
 | 
				
			||||||
    Token.objects.filter(
 | 
					 | 
				
			||||||
        identifier=instance.service_account_identifier, intent=TokenIntents.INTENT_API
 | 
					 | 
				
			||||||
    ).delete()
 | 
					 | 
				
			||||||
    User.objects.filter(
 | 
					    User.objects.filter(
 | 
				
			||||||
        username=instance.service_account_identifier, type=UserTypes.INTERNAL_SERVICE_ACCOUNT
 | 
					        username=instance.service_account_identifier, type=UserTypes.INTERNAL_SERVICE_ACCOUNT
 | 
				
			||||||
    ).delete()
 | 
					    ).delete()
 | 
				
			||||||
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user