diff --git a/authentik/outposts/models.py b/authentik/outposts/models.py index a4a822964..48fbb325e 100644 --- a/authentik/outposts/models.py +++ b/authentik/outposts/models.py @@ -341,19 +341,8 @@ class Outpost(ManagedModel): """Username for service user""" return f"ak-outpost-{self.uuid.hex}" - @property - def user(self) -> User: - """Get/create user with access to all required objects""" - users = User.objects.filter(username=self.user_identifier) - if not users.exists(): - user: User = User.objects.create(username=self.user_identifier) - user.set_unusable_password() - user.save() - else: - user = users.first() - user.attributes[USER_ATTRIBUTE_SA] = True - user.attributes[USER_ATTRIBUTE_CAN_OVERRIDE_IP] = True - user.save() + def build_user_permissions(self, user: User): + """Create per-object and global permissions for outpost service-account""" # To ensure the user only has the correct permissions, we delete all of them and re-add # the ones the user needs with transaction.atomic(): @@ -397,6 +386,23 @@ class Outpost(ManagedModel): "Updated service account's permissions", perms=UserObjectPermission.objects.filter(user=user), ) + + @property + def user(self) -> User: + """Get/create user with access to all required objects""" + users = User.objects.filter(username=self.user_identifier) + should_create_user = not users.exists() + if should_create_user: + user: User = User.objects.create(username=self.user_identifier) + user.set_unusable_password() + user.save() + else: + user = users.first() + user.attributes[USER_ATTRIBUTE_SA] = True + user.attributes[USER_ATTRIBUTE_CAN_OVERRIDE_IP] = True + user.save() + if should_create_user: + self.build_user_permissions(user) return user @property diff --git a/authentik/outposts/tasks.py b/authentik/outposts/tasks.py index 549f2e32b..fb2db9c77 100644 --- a/authentik/outposts/tasks.py +++ b/authentik/outposts/tasks.py @@ -126,6 +126,7 @@ def outpost_token_ensurer(self: MonitoredTask): all_outposts = Outpost.objects.all() for outpost in all_outposts: _ = outpost.token + outpost.build_user_permissions(outpost.user) self.set_status( TaskResult( TaskResultStatus.SUCCESSFUL, @@ -196,7 +197,7 @@ def _outpost_single_update(outpost: Outpost, layer=None): # Ensure token again, because this function is called when anything related to an # OutpostModel is saved, so we can be sure permissions are right _ = outpost.token - _ = outpost.user + outpost.build_user_permissions(outpost.user) if not layer: # pragma: no cover layer = get_channel_layer() for state in OutpostState.for_outpost(outpost): diff --git a/tests/e2e/test_provider_proxy.py b/tests/e2e/test_provider_proxy.py index 4bc18a14a..1bd260a64 100644 --- a/tests/e2e/test_provider_proxy.py +++ b/tests/e2e/test_provider_proxy.py @@ -86,7 +86,7 @@ class TestProviderProxy(SeleniumTestCase): ) outpost.providers.add(proxy) outpost.save() - _ = outpost.user + outpost.build_user_permissions(outpost.user) self.proxy_container = self.start_proxy(outpost) @@ -150,7 +150,7 @@ class TestProviderProxyConnect(ChannelsLiveServerTestCase): ) outpost.providers.add(proxy) outpost.save() - _ = outpost.user + outpost.build_user_permissions(outpost.user) # Wait until outpost healthcheck succeeds healthcheck_retries = 0