mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-24 13:01:56 +00:00
fix(admincenter): restrict admincenter group visibility check to Unified groups (#10899)
This commit is contained in:
committed by
GitHub
parent
fb6da427f8
commit
368d9c1519
@@ -14,6 +14,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
### 🐞 Fixed
|
||||
|
||||
- Alibaba Cloud CS service SDK compatibility, harden other services and improve documentation [(#10871)](https://github.com/prowler-cloud/prowler/pull/10871)
|
||||
- `admincenter_groups_not_public_visibility` check for M365 provider evaluating Security and Distribution groups, now restricted to Microsoft 365 (Unified) groups per CIS M365 Foundations 1.2.1 [(#10899)](https://github.com/prowler-cloud/prowler/pull/10899)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+5
@@ -27,6 +27,11 @@ class admincenter_groups_not_public_visibility(Check):
|
||||
"""
|
||||
findings = []
|
||||
for group in admincenter_client.groups.values():
|
||||
# Only Microsoft 365 Groups (identified by the "Unified" group type) are in
|
||||
# scope for this check per CIS M365 Foundations 1.2.1. Security,
|
||||
# Distribution, and other group types are skipped.
|
||||
if "Unified" not in group.group_types:
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=group,
|
||||
|
||||
@@ -182,6 +182,7 @@ class AdminCenter(M365Service):
|
||||
id=group.id,
|
||||
name=getattr(group, "display_name", ""),
|
||||
visibility=getattr(group, "visibility", ""),
|
||||
group_types=getattr(group, "group_types", []) or [],
|
||||
)
|
||||
}
|
||||
)
|
||||
@@ -237,6 +238,7 @@ class Group(BaseModel):
|
||||
id: str
|
||||
name: str
|
||||
visibility: Optional[str]
|
||||
group_types: List[str] = []
|
||||
|
||||
|
||||
class PasswordPolicy(BaseModel):
|
||||
|
||||
+81
-4
@@ -61,7 +61,12 @@ class Test_admincenter_groups_not_public_visibility:
|
||||
id_group1 = str(uuid4())
|
||||
|
||||
admincenter_client.groups = {
|
||||
id_group1: Group(id=id_group1, name="Group1", visibility="Private"),
|
||||
id_group1: Group(
|
||||
id=id_group1,
|
||||
name="Group1",
|
||||
visibility="Private",
|
||||
group_types=["Unified"],
|
||||
),
|
||||
}
|
||||
|
||||
check = admincenter_groups_not_public_visibility()
|
||||
@@ -102,7 +107,12 @@ class Test_admincenter_groups_not_public_visibility:
|
||||
id_group1 = str(uuid4())
|
||||
|
||||
admincenter_client.groups = {
|
||||
id_group1: Group(id=id_group1, name="Group1", visibility="Private"),
|
||||
id_group1: Group(
|
||||
id=id_group1,
|
||||
name="Group1",
|
||||
visibility="Private",
|
||||
group_types=["Unified"],
|
||||
),
|
||||
}
|
||||
|
||||
check = admincenter_groups_not_public_visibility()
|
||||
@@ -143,7 +153,12 @@ class Test_admincenter_groups_not_public_visibility:
|
||||
id_group1 = str(uuid4())
|
||||
|
||||
admincenter_client.groups = {
|
||||
id_group1: Group(id=id_group1, name="Group1", visibility="Public"),
|
||||
id_group1: Group(
|
||||
id=id_group1,
|
||||
name="Group1",
|
||||
visibility="Public",
|
||||
group_types=["Unified"],
|
||||
),
|
||||
}
|
||||
|
||||
check = admincenter_groups_not_public_visibility()
|
||||
@@ -187,7 +202,12 @@ class Test_admincenter_groups_not_public_visibility:
|
||||
id_group1 = str(uuid4())
|
||||
|
||||
admincenter_client.groups = {
|
||||
id_group1: Group(id=id_group1, name="Group1", visibility=None),
|
||||
id_group1: Group(
|
||||
id=id_group1,
|
||||
name="Group1",
|
||||
visibility=None,
|
||||
group_types=["Unified"],
|
||||
),
|
||||
}
|
||||
|
||||
check = admincenter_groups_not_public_visibility()
|
||||
@@ -202,3 +222,60 @@ class Test_admincenter_groups_not_public_visibility:
|
||||
assert result[0].resource_name == "Group1"
|
||||
assert result[0].resource_id == id_group1
|
||||
assert result[0].location == "global"
|
||||
|
||||
def test_admincenter_security_group_ignored(self):
|
||||
admincenter_client = mock.MagicMock
|
||||
admincenter_client.audited_tenant = "audited_tenant"
|
||||
admincenter_client.audited_domain = DOMAIN
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=set_mocked_m365_provider(),
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.m365.lib.powershell.m365_powershell.M365PowerShell.connect_exchange_online"
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility.admincenter_client",
|
||||
new=admincenter_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.admincenter.admincenter_groups_not_public_visibility.admincenter_groups_not_public_visibility import (
|
||||
admincenter_groups_not_public_visibility,
|
||||
)
|
||||
from prowler.providers.m365.services.admincenter.admincenter_service import (
|
||||
Group,
|
||||
)
|
||||
|
||||
id_security_group = str(uuid4())
|
||||
id_distribution_group = str(uuid4())
|
||||
id_m365_group = str(uuid4())
|
||||
|
||||
admincenter_client.groups = {
|
||||
id_security_group: Group(
|
||||
id=id_security_group,
|
||||
name="SecurityGroup",
|
||||
visibility=None,
|
||||
group_types=[],
|
||||
),
|
||||
id_distribution_group: Group(
|
||||
id=id_distribution_group,
|
||||
name="DistributionGroup",
|
||||
visibility=None,
|
||||
group_types=[],
|
||||
),
|
||||
id_m365_group: Group(
|
||||
id=id_m365_group,
|
||||
name="M365Group",
|
||||
visibility="Private",
|
||||
group_types=["Unified"],
|
||||
),
|
||||
}
|
||||
|
||||
check = admincenter_groups_not_public_visibility()
|
||||
result = check.execute()
|
||||
assert len(result) == 1
|
||||
assert result[0].resource_id == id_m365_group
|
||||
assert result[0].status == "PASS"
|
||||
assert result[0].resource_name == "M365Group"
|
||||
|
||||
@@ -214,3 +214,41 @@ def test_admincenter__get_users_handles_pagination():
|
||||
with_url_mock.assert_called_once_with("next-link")
|
||||
assert users["user-1"].license == "SKU-user-1"
|
||||
assert users["user-3"].license == "SKU-user-3"
|
||||
|
||||
|
||||
def test_admincenter__get_groups_maps_group_types():
|
||||
admincenter_service = AdminCenter.__new__(AdminCenter)
|
||||
|
||||
groups_response = SimpleNamespace(
|
||||
value=[
|
||||
SimpleNamespace(
|
||||
id="id-1",
|
||||
display_name="Unified Group",
|
||||
visibility="Private",
|
||||
group_types=["Unified"],
|
||||
),
|
||||
SimpleNamespace(
|
||||
id="id-2",
|
||||
display_name="Security Group",
|
||||
visibility=None,
|
||||
group_types=[],
|
||||
),
|
||||
SimpleNamespace(
|
||||
id="id-3",
|
||||
display_name="Legacy Group",
|
||||
visibility="Public",
|
||||
),
|
||||
]
|
||||
)
|
||||
|
||||
groups_builder = SimpleNamespace(get=AsyncMock(return_value=groups_response))
|
||||
admincenter_service.client = SimpleNamespace(groups=groups_builder)
|
||||
|
||||
groups = asyncio.run(admincenter_service._get_groups())
|
||||
|
||||
assert len(groups) == 3
|
||||
assert groups_builder.get.await_count == 1
|
||||
assert groups["id-1"].group_types == ["Unified"]
|
||||
assert groups["id-2"].group_types == []
|
||||
assert groups["id-3"].group_types == []
|
||||
assert groups["id-3"].visibility == "Public"
|
||||
|
||||
Reference in New Issue
Block a user