From 8162c1ec86f656b5a560747dc797ed267b1e9f33 Mon Sep 17 00:00:00 2001 From: Jens L Date: Mon, 20 May 2024 14:16:34 +0200 Subject: [PATCH] enterprise/providers/google_workspace: ensure no group is created when no property mappings are set (#9783) * enterprise/providers/google_workspace: ensure no group is created when no property mappings are set Signed-off-by: Jens Langhammer * add tests for that to all sync providers Signed-off-by: Jens Langhammer --------- Signed-off-by: Jens Langhammer --- .../google_workspace/clients/groups.py | 8 ++--- .../google_workspace/clients/users.py | 3 +- .../google_workspace/tests/test_groups.py | 21 +++++++++++ .../google_workspace/tests/test_users.py | 25 +++++++++++++ .../microsoft_entra/tests/test_groups.py | 32 +++++++++++++++++ .../microsoft_entra/tests/test_users.py | 36 +++++++++++++++++++ 6 files changed, 119 insertions(+), 6 deletions(-) diff --git a/authentik/enterprise/providers/google_workspace/clients/groups.py b/authentik/enterprise/providers/google_workspace/clients/groups.py index 41c1fd5563..cde6eaeec4 100644 --- a/authentik/enterprise/providers/google_workspace/clients/groups.py +++ b/authentik/enterprise/providers/google_workspace/clients/groups.py @@ -36,9 +36,7 @@ class GoogleWorkspaceGroupClient( def to_schema(self, obj: Group, creating: bool) -> dict: """Convert authentik group""" - raw_google_group = { - "email": f"{slugify(obj.name)}@{self.provider.default_group_email_domain}" - } + raw_google_group = {} for mapping in ( self.provider.property_mappings_group.all().order_by("name").select_subclasses() ): @@ -67,7 +65,9 @@ class GoogleWorkspaceGroupClient( raise StopSync(exc, obj, mapping) from exc if not raw_google_group: raise StopSync(ValueError("No group mappings configured"), obj) - + raw_google_group.setdefault( + "email", f"{slugify(obj.name)}@{self.provider.default_group_email_domain}" + ) return raw_google_group def delete(self, obj: Group): diff --git a/authentik/enterprise/providers/google_workspace/clients/users.py b/authentik/enterprise/providers/google_workspace/clients/users.py index 5f91e01838..03db3eded7 100644 --- a/authentik/enterprise/providers/google_workspace/clients/users.py +++ b/authentik/enterprise/providers/google_workspace/clients/users.py @@ -57,8 +57,7 @@ class GoogleWorkspaceUserClient(GoogleWorkspaceSyncClient[User, GoogleWorkspaceP raise StopSync(exc, obj, mapping) from exc if not raw_google_user: raise StopSync(ValueError("No user mappings configured"), obj) - if "primaryEmail" not in raw_google_user: - raw_google_user["primaryEmail"] = str(obj.email) + raw_google_user.setdefault("primaryEmail", str(obj.email)) return delete_none_values(raw_google_user) def delete(self, obj: User): diff --git a/authentik/enterprise/providers/google_workspace/tests/test_groups.py b/authentik/enterprise/providers/google_workspace/tests/test_groups.py index 6df1668f14..fbc52a94aa 100644 --- a/authentik/enterprise/providers/google_workspace/tests/test_groups.py +++ b/authentik/enterprise/providers/google_workspace/tests/test_groups.py @@ -82,6 +82,27 @@ class GoogleWorkspaceGroupTests(TestCase): self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) self.assertEqual(len(http.requests()), 2) + def test_group_not_created(self): + """Test without group property mappings, no group is created""" + self.provider.property_mappings_group.clear() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + group = Group.objects.create(name=uid) + google_group = GoogleWorkspaceProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNone(google_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 1) + def test_group_create_update(self): """Test group updating""" uid = generate_id() diff --git a/authentik/enterprise/providers/google_workspace/tests/test_users.py b/authentik/enterprise/providers/google_workspace/tests/test_users.py index a19e1d3591..0f7ec0d14e 100644 --- a/authentik/enterprise/providers/google_workspace/tests/test_users.py +++ b/authentik/enterprise/providers/google_workspace/tests/test_users.py @@ -86,6 +86,31 @@ class GoogleWorkspaceUserTests(TestCase): self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) self.assertEqual(len(http.requests()), 2) + def test_user_not_created(self): + """Test without property mappings, no group is created""" + self.provider.property_mappings.clear() + uid = generate_id() + http = MockHTTP() + http.add_response( + f"https://admin.googleapis.com/admin/directory/v1/customer/my_customer/domains?key={self.api_key}&alt=json", + domains_list_v1_mock, + ) + with patch( + "authentik.enterprise.providers.google_workspace.models.GoogleWorkspaceProvider.google_credentials", + MagicMock(return_value={"developerKey": self.api_key, "http": http}), + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + google_user = GoogleWorkspaceProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNone(google_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + self.assertEqual(len(http.requests()), 1) + def test_user_create_update(self): """Test user updating""" uid = generate_id() diff --git a/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py b/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py index 8675374d78..c39d0ca206 100644 --- a/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py +++ b/authentik/enterprise/providers/microsoft_entra/tests/test_groups.py @@ -93,6 +93,38 @@ class MicrosoftEntraGroupTests(TestCase): self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) group_create.assert_called_once() + def test_group_not_created(self): + """Test without group property mappings, no group is created""" + self.provider.property_mappings_group.clear() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.groups.groups_request_builder.GroupsRequestBuilder.post", + AsyncMock(return_value=MSGroup(id=generate_id())), + ) as group_create, + ): + group = Group.objects.create(name=uid) + microsoft_group = MicrosoftEntraProviderGroup.objects.filter( + provider=self.provider, group=group + ).first() + self.assertIsNone(microsoft_group) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + group_create.assert_not_called() + def test_group_create_update(self): """Test group updating""" uid = generate_id() diff --git a/authentik/enterprise/providers/microsoft_entra/tests/test_users.py b/authentik/enterprise/providers/microsoft_entra/tests/test_users.py index adef82f29e..7a00213efc 100644 --- a/authentik/enterprise/providers/microsoft_entra/tests/test_users.py +++ b/authentik/enterprise/providers/microsoft_entra/tests/test_users.py @@ -94,6 +94,42 @@ class MicrosoftEntraUserTests(TestCase): self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) user_create.assert_called_once() + def test_user_not_created(self): + """Test without property mappings, no group is created""" + self.provider.property_mappings.clear() + uid = generate_id() + with ( + patch( + "authentik.enterprise.providers.microsoft_entra.models.MicrosoftEntraProvider.microsoft_credentials", + MagicMock(return_value={"credentials": self.creds}), + ), + patch( + "msgraph.generated.organization.organization_request_builder.OrganizationRequestBuilder.get", + AsyncMock( + return_value=OrganizationCollectionResponse( + value=[ + Organization(verified_domains=[VerifiedDomain(name="goauthentik.io")]) + ] + ) + ), + ), + patch( + "msgraph.generated.users.users_request_builder.UsersRequestBuilder.post", + AsyncMock(return_value=MSUser(id=generate_id())), + ) as user_create, + ): + user = User.objects.create( + username=uid, + name=f"{uid} {uid}", + email=f"{uid}@goauthentik.io", + ) + microsoft_user = MicrosoftEntraProviderUser.objects.filter( + provider=self.provider, user=user + ).first() + self.assertIsNone(microsoft_user) + self.assertFalse(Event.objects.filter(action=EventAction.SYSTEM_EXCEPTION).exists()) + user_create.assert_not_called() + def test_user_create_update(self): """Test user updating""" uid = generate_id()