Compare commits

...

1 Commits

Author SHA1 Message Date
HugoPBrito
5e75814194 feat(m365): add entra_policy_unknown_unsupported_device_platforms_blocked security check
Add new security check entra_policy_unknown_unsupported_device_platforms_blocked for m365 provider.
Includes check implementation, metadata, and unit tests.
2026-02-13 10:52:55 +01:00
7 changed files with 869 additions and 7 deletions

View File

@@ -17,6 +17,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
- OCI regions updater script and CI workflow [(#10020)](https://github.com/prowler-cloud/prowler/pull/10020)
- `image` provider for container image scanning with Trivy integration [(#9984)](https://github.com/prowler-cloud/prowler/pull/9984)
- CSA CCM 4.0 for the Alibaba Cloud provider [(#10061)](https://github.com/prowler-cloud/prowler/pull/10061)
- `entra_policy_unknown_unsupported_device_platforms_blocked` check for M365 provider [(#10063)](https://github.com/prowler-cloud/prowler/pull/10063)
### 🔄 Changed

View File

@@ -199,7 +199,8 @@
"admincenter_users_admins_reduced_license_footprint",
"entra_admin_portals_access_restriction",
"entra_admin_users_phishing_resistant_mfa_enabled",
"entra_policy_guest_users_access_restrictions"
"entra_policy_guest_users_access_restrictions",
"entra_policy_unknown_unsupported_device_platforms_blocked"
]
},
{
@@ -603,10 +604,11 @@
],
"Checks": [
"entra_managed_device_required_for_authentication",
"entra_users_mfa_enabled",
"entra_managed_device_required_for_mfa_registration",
"entra_admin_users_phishing_resistant_mfa_enabled",
"entra_users_mfa_capable"
"entra_policy_unknown_unsupported_device_platforms_blocked",
"entra_users_mfa_capable",
"entra_users_mfa_enabled",
"entra_admin_users_phishing_resistant_mfa_enabled"
]
},
{
@@ -670,11 +672,12 @@
}
],
"Checks": [
"entra_admin_users_sign_in_frequency_enabled",
"entra_admin_users_mfa_enabled",
"entra_admin_users_sign_in_frequency_enabled",
"entra_identity_protection_sign_in_risk_enabled",
"entra_managed_device_required_for_authentication",
"entra_users_mfa_enabled",
"entra_identity_protection_sign_in_risk_enabled"
"entra_policy_unknown_unsupported_device_platforms_blocked",
"entra_users_mfa_enabled"
]
},
{

View File

@@ -0,0 +1,37 @@
{
"Provider": "m365",
"CheckID": "entra_policy_unknown_unsupported_device_platforms_blocked",
"CheckTitle": "Conditional Access policy blocks unknown or unsupported device platforms",
"CheckType": [],
"ServiceName": "entra",
"SubServiceName": "",
"ResourceIdTemplate": "",
"Severity": "medium",
"ResourceType": "Conditional Access Policy",
"ResourceGroup": "IAM",
"Description": "Conditional Access policy blocks access from **unknown or unsupported device platforms** to protect the tenant from unmanaged or potentially compromised endpoints.\n\nThis check verifies that at least one enabled policy exists that blocks all device platforms, which includes unknown or unsupported platforms by default.",
"Risk": "Without blocking unknown or unsupported device platforms, attackers may exploit unmanaged endpoints to gain unauthorized access.\n\n- **Unverified devices** may lack security controls\n- **Legacy platforms** may have known vulnerabilities\n- Devices with **spoofed user agents** could bypass security measures",
"RelatedUrl": "",
"AdditionalURLs": [
"https://learn.microsoft.com/en-us/entra/identity/conditional-access/concept-conditional-access-conditions#device-platforms",
"https://maester.dev/docs/tests/MT.1015"
],
"Remediation": {
"Code": {
"CLI": "",
"NativeIaC": "",
"Other": "1. Navigate to the Microsoft Entra admin center https://entra.microsoft.com\n2. Expand **Protection** > **Conditional Access** and select **Policies**\n3. Click **New policy**\n4. Under **Users**, include **All users**\n5. Under **Target resources**, include **All cloud apps**\n6. Under **Conditions** > **Device platforms**, configure as **Yes** and select **Any device**\n7. Under **Grant**, select **Block access**\n8. Set the policy state to **On** and click **Create**",
"Terraform": ""
},
"Recommendation": {
"Text": "Create a Conditional Access policy that blocks access from all device platforms and uses exclusions for known, supported platforms like Windows, macOS, iOS, and Android. This approach ensures that unknown or unsupported platforms are blocked by default.",
"Url": "https://hub.prowler.com/check/entra_policy_unknown_unsupported_device_platforms_blocked"
}
},
"Categories": [
"e3"
],
"DependsOn": [],
"RelatedTo": [],
"Notes": "This check is based on Maester test MT.1015 - Test-MtCaBlockUnknownOrUnsupportedDevicePlatform."
}

View File

@@ -0,0 +1,73 @@
from prowler.lib.check.models import Check, CheckReportM365
from prowler.providers.m365.services.entra.entra_client import entra_client
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessGrantControl,
ConditionalAccessPolicyState,
DevicePlatform,
)
class entra_policy_unknown_unsupported_device_platforms_blocked(Check):
"""Check if at least one Conditional Access policy blocks unknown or unsupported device platforms.
This check verifies that the tenant has at least one enabled Conditional Access
policy configured to block access from unknown or unsupported device platforms.
- PASS: At least one enabled policy blocks all device platforms.
- FAIL: No policy is configured to block unknown or unsupported device platforms.
"""
def execute(self) -> list[CheckReportM365]:
"""Execute the check for Conditional Access policy blocking unknown device platforms.
Returns:
list[CheckReportM365]: A list containing the results of the check.
"""
findings = []
report = CheckReportM365(
metadata=self.metadata(),
resource={},
resource_name="Conditional Access Policies",
resource_id="conditionalAccessPolicies",
)
report.status = "FAIL"
report.status_extended = "No Conditional Access Policy blocks unknown or unsupported device platforms."
for policy in entra_client.conditional_access_policies.values():
# Skip disabled policies
if policy.state == ConditionalAccessPolicyState.DISABLED:
continue
# Check if policy has block control
if (
ConditionalAccessGrantControl.BLOCK
not in policy.grant_controls.built_in_controls
):
continue
# Check if policy targets all platforms
if (
policy.conditions.platform_conditions is None
or DevicePlatform.ALL
not in policy.conditions.platform_conditions.included_platforms
):
continue
# Policy meets all criteria
report = CheckReportM365(
metadata=self.metadata(),
resource=policy,
resource_name=policy.display_name,
resource_id=policy.id,
)
if policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
report.status = "FAIL"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' reports unknown device platforms but does not block them."
else:
report.status = "PASS"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' blocks unknown or unsupported device platforms."
break
findings.append(report)
return findings

View File

@@ -235,6 +235,30 @@ class Entra(M365Service):
[],
)
],
platform_conditions=(
PlatformConditions(
included_platforms=[
DevicePlatform(platform.value)
for platform in getattr(
policy.conditions.platforms,
"include_platforms",
[],
)
or []
],
excluded_platforms=[
DevicePlatform(platform.value)
for platform in getattr(
policy.conditions.platforms,
"exclude_platforms",
[],
)
or []
],
)
if getattr(policy.conditions, "platforms", None)
else None
),
),
grant_controls=GrantControls(
built_in_controls=(
@@ -503,12 +527,33 @@ class ClientAppType(Enum):
OTHER_CLIENTS = "other"
class DevicePlatform(Enum):
"""Device platforms for Conditional Access policies."""
ANDROID = "android"
IOS = "iOS"
WINDOWS = "windows"
WINDOWS_PHONE = "windowsPhone"
MAC_OS = "macOS"
LINUX = "linux"
ALL = "all"
UNKNOWN_FUTURE_VALUE = "unknownFutureValue"
class PlatformConditions(BaseModel):
"""Platform conditions for Conditional Access policies."""
included_platforms: List[DevicePlatform] = []
excluded_platforms: List[DevicePlatform] = []
class Conditions(BaseModel):
application_conditions: Optional[ApplicationsConditions]
user_conditions: Optional[UsersConditions]
client_app_types: Optional[List[ClientAppType]]
user_risk_levels: List[RiskLevel] = []
sign_in_risk_levels: List[RiskLevel] = []
platform_conditions: Optional[PlatformConditions] = None
class PersistentBrowser(BaseModel):

View File

@@ -0,0 +1,703 @@
from unittest import mock
from uuid import uuid4
from prowler.providers.m365.services.entra.entra_service import (
ApplicationsConditions,
ConditionalAccessGrantControl,
ConditionalAccessPolicyState,
Conditions,
DevicePlatform,
GrantControlOperator,
GrantControls,
PersistentBrowser,
PlatformConditions,
SessionControls,
SignInFrequency,
SignInFrequencyInterval,
UsersConditions,
)
from tests.providers.m365.m365_fixtures import DOMAIN, set_mocked_m365_provider
class Test_entra_policy_unknown_unsupported_device_platforms_blocked:
"""Test cases for entra_policy_unknown_unsupported_device_platforms_blocked check."""
def test_entra_no_conditional_access_policies(self):
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
entra_client.conditional_access_policies = {}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "No Conditional Access Policy blocks unknown or unsupported device platforms."
)
assert result[0].resource == {}
assert result[0].resource_name == "Conditional Access Policies"
assert result[0].resource_id == "conditionalAccessPolicies"
assert result[0].location == "global"
def test_entra_policy_disabled(self):
policy_id = str(uuid4())
display_name = "Block Unknown Platforms"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[
DevicePlatform.ANDROID,
DevicePlatform.IOS,
DevicePlatform.WINDOWS,
DevicePlatform.MAC_OS,
],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.DISABLED,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "No Conditional Access Policy blocks unknown or unsupported device platforms."
)
assert result[0].resource == {}
assert result[0].resource_name == "Conditional Access Policies"
assert result[0].resource_id == "conditionalAccessPolicies"
assert result[0].location == "global"
def test_entra_policy_no_block_control(self):
policy_id = str(uuid4())
display_name = "Policy Without Block"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.MFA,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "No Conditional Access Policy blocks unknown or unsupported device platforms."
)
assert result[0].resource == {}
assert result[0].resource_name == "Conditional Access Policies"
assert result[0].resource_id == "conditionalAccessPolicies"
assert result[0].location == "global"
def test_entra_policy_no_platform_conditions(self):
policy_id = str(uuid4())
display_name = "Policy Without Platform Conditions"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=None,
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "No Conditional Access Policy blocks unknown or unsupported device platforms."
)
assert result[0].resource == {}
assert result[0].resource_name == "Conditional Access Policies"
assert result[0].resource_id == "conditionalAccessPolicies"
assert result[0].location == "global"
def test_entra_policy_platform_not_all(self):
policy_id = str(uuid4())
display_name = "Policy With Specific Platforms"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[
DevicePlatform.ANDROID,
DevicePlatform.IOS,
],
excluded_platforms=[],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== "No Conditional Access Policy blocks unknown or unsupported device platforms."
)
assert result[0].resource == {}
assert result[0].resource_name == "Conditional Access Policies"
assert result[0].resource_id == "conditionalAccessPolicies"
assert result[0].location == "global"
def test_entra_policy_enabled_for_reporting(self):
policy_id = str(uuid4())
display_name = "Block Unknown Platforms - Report Only"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED_FOR_REPORTING,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert (
result[0].status_extended
== f"Conditional Access Policy '{display_name}' reports unknown device platforms but does not block them."
)
assert (
result[0].resource
== entra_client.conditional_access_policies[policy_id].dict()
)
assert result[0].resource_name == display_name
assert result[0].resource_id == policy_id
assert result[0].location == "global"
def test_entra_policy_enabled_blocks_unknown_platforms(self):
policy_id = str(uuid4())
display_name = "Block Unknown Platforms"
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
policy_id: ConditionalAccessPolicy(
id=policy_id,
display_name=display_name,
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[
DevicePlatform.ANDROID,
DevicePlatform.IOS,
DevicePlatform.WINDOWS,
DevicePlatform.MAC_OS,
],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED,
)
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== f"Conditional Access Policy '{display_name}' blocks unknown or unsupported device platforms."
)
assert (
result[0].resource
== entra_client.conditional_access_policies[policy_id].dict()
)
assert result[0].resource_name == display_name
assert result[0].resource_id == policy_id
assert result[0].location == "global"
def test_entra_multiple_policies_one_valid(self):
disabled_policy_id = str(uuid4())
enabled_policy_id = str(uuid4())
entra_client = mock.MagicMock
entra_client.audited_tenant = "audited_tenant"
entra_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.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_policy_unknown_unsupported_device_platforms_blocked.entra_policy_unknown_unsupported_device_platforms_blocked import (
entra_policy_unknown_unsupported_device_platforms_blocked,
)
from prowler.providers.m365.services.entra.entra_service import (
ConditionalAccessPolicy,
)
entra_client.conditional_access_policies = {
disabled_policy_id: ConditionalAccessPolicy(
id=disabled_policy_id,
display_name="Disabled Policy",
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.DISABLED,
),
enabled_policy_id: ConditionalAccessPolicy(
id=enabled_policy_id,
display_name="Enabled Block Policy",
conditions=Conditions(
application_conditions=ApplicationsConditions(
included_applications=["All"],
excluded_applications=[],
included_user_actions=[],
),
user_conditions=UsersConditions(
included_groups=[],
excluded_groups=[],
included_users=["All"],
excluded_users=[],
included_roles=[],
excluded_roles=[],
),
client_app_types=[],
user_risk_levels=[],
platform_conditions=PlatformConditions(
included_platforms=[DevicePlatform.ALL],
excluded_platforms=[],
),
),
grant_controls=GrantControls(
built_in_controls=[
ConditionalAccessGrantControl.BLOCK,
],
operator=GrantControlOperator.AND,
authentication_strength=None,
),
session_controls=SessionControls(
persistent_browser=PersistentBrowser(
is_enabled=False, mode="always"
),
sign_in_frequency=SignInFrequency(
is_enabled=False,
frequency=None,
type=None,
interval=SignInFrequencyInterval.EVERY_TIME,
),
),
state=ConditionalAccessPolicyState.ENABLED,
),
}
check = entra_policy_unknown_unsupported_device_platforms_blocked()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert (
result[0].status_extended
== "Conditional Access Policy 'Enabled Block Policy' blocks unknown or unsupported device platforms."
)
assert result[0].resource_name == "Enabled Block Policy"
assert result[0].resource_id == enabled_policy_id
assert result[0].location == "global"