mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-09 21:14:22 +00:00
fix(m365): paginate admincenter group enumeration (#11510)
This commit is contained in:
@@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
### 🐞 Fixed
|
||||
|
||||
- `load_and_validate_config_file` now unwraps namespaced config for every built-in and external provider, and no longer leaks the full file as the provider's config when the file is namespaced [(#10700)](https://github.com/prowler-cloud/prowler/pull/10700)
|
||||
- M365 Admin Center group enumeration now follows Microsoft Graph pagination so group-scoped checks include groups beyond the first page [(#11510)](https://github.com/prowler-cloud/prowler/pull/11510)
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -175,17 +175,23 @@ class AdminCenter(M365Service):
|
||||
try:
|
||||
groups_list = await self.client.groups.get()
|
||||
groups.update({})
|
||||
for group in groups_list.value:
|
||||
groups.update(
|
||||
{
|
||||
group.id: Group(
|
||||
id=group.id,
|
||||
name=getattr(group, "display_name", ""),
|
||||
visibility=getattr(group, "visibility", ""),
|
||||
group_types=getattr(group, "group_types", []) or [],
|
||||
)
|
||||
}
|
||||
)
|
||||
while groups_list:
|
||||
for group in getattr(groups_list, "value", []) or []:
|
||||
groups.update(
|
||||
{
|
||||
group.id: Group(
|
||||
id=group.id,
|
||||
name=getattr(group, "display_name", ""),
|
||||
visibility=getattr(group, "visibility", ""),
|
||||
group_types=getattr(group, "group_types", []) or [],
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
next_link = getattr(groups_list, "odata_next_link", None)
|
||||
if not next_link:
|
||||
break
|
||||
groups_list = await self.client.groups.with_url(next_link).get()
|
||||
|
||||
except Exception as error:
|
||||
logger.error(
|
||||
|
||||
@@ -252,3 +252,49 @@ def test_admincenter__get_groups_maps_group_types():
|
||||
assert groups["id-2"].group_types == []
|
||||
assert groups["id-3"].group_types == []
|
||||
assert groups["id-3"].visibility == "Public"
|
||||
|
||||
|
||||
def test_admincenter__get_groups_handles_pagination():
|
||||
admincenter_service = AdminCenter.__new__(AdminCenter)
|
||||
|
||||
groups_response_page_one = SimpleNamespace(
|
||||
value=[
|
||||
SimpleNamespace(
|
||||
id="id-1",
|
||||
display_name="First Unified Group",
|
||||
visibility="Private",
|
||||
group_types=["Unified"],
|
||||
)
|
||||
],
|
||||
odata_next_link="next-link",
|
||||
)
|
||||
groups_response_page_two = SimpleNamespace(
|
||||
value=[
|
||||
SimpleNamespace(
|
||||
id="id-2",
|
||||
display_name="Second Unified Group",
|
||||
visibility="Public",
|
||||
group_types=["Unified"],
|
||||
)
|
||||
],
|
||||
odata_next_link=None,
|
||||
)
|
||||
|
||||
groups_with_url_builder = SimpleNamespace(
|
||||
get=AsyncMock(return_value=groups_response_page_two)
|
||||
)
|
||||
with_url_mock = MagicMock(return_value=groups_with_url_builder)
|
||||
groups_builder = SimpleNamespace(
|
||||
get=AsyncMock(return_value=groups_response_page_one),
|
||||
with_url=with_url_mock,
|
||||
)
|
||||
admincenter_service.client = SimpleNamespace(groups=groups_builder)
|
||||
|
||||
groups = asyncio.run(admincenter_service._get_groups())
|
||||
|
||||
assert len(groups) == 2
|
||||
assert groups_builder.get.await_count == 1
|
||||
with_url_mock.assert_called_once_with("next-link")
|
||||
assert groups["id-1"].name == "First Unified Group"
|
||||
assert groups["id-2"].name == "Second Unified Group"
|
||||
assert groups["id-2"].visibility == "Public"
|
||||
|
||||
Reference in New Issue
Block a user