mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-08-19 09:30:21 +00:00
refactor(m365): normalize CA platforms at model level (#10635)
Co-authored-by: Hugo P.Brito <hugopbrito@Mac.home>
This commit is contained in:
co-authored by
Hugo P.Brito
parent
90a619a8b4
commit
a82eaa885d
@@ -21,6 +21,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
### 🔄 Changed
|
||||
|
||||
- Bump Poetry to `2.3.4` and consolidate SDK workflows onto the `setup-python-poetry` composite action with opt-in lockfile regeneration [(#10681)](https://github.com/prowler-cloud/prowler/pull/10681)
|
||||
- Normalize Conditional Access platform values in Entra models and simplify platform-based checks [(#10635)](https://github.com/prowler-cloud/prowler/pull/10635)
|
||||
|
||||
---
|
||||
|
||||
|
||||
+8
-25
@@ -23,13 +23,6 @@ class entra_conditional_access_policy_approved_client_app_required_for_mobile(Ch
|
||||
ConditionalAccessGrantControl.COMPLIANT_APPLICATION,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def _normalize_platform(platform: object) -> str:
|
||||
normalized_platform = getattr(platform, "value", platform)
|
||||
return (
|
||||
normalized_platform.lower() if isinstance(normalized_platform, str) else ""
|
||||
)
|
||||
|
||||
def execute(self) -> list[CheckReportM365]:
|
||||
"""Execute the check logic.
|
||||
|
||||
@@ -54,22 +47,12 @@ class entra_conditional_access_policy_approved_client_app_required_for_mobile(Ch
|
||||
if not policy.conditions.platform_conditions:
|
||||
continue
|
||||
|
||||
included_platforms = {
|
||||
normalized_platform
|
||||
for normalized_platform in map(
|
||||
self._normalize_platform,
|
||||
policy.conditions.platform_conditions.include_platforms,
|
||||
)
|
||||
if normalized_platform
|
||||
}
|
||||
excluded_platforms = {
|
||||
normalized_platform
|
||||
for normalized_platform in map(
|
||||
self._normalize_platform,
|
||||
policy.conditions.platform_conditions.exclude_platforms,
|
||||
)
|
||||
if normalized_platform
|
||||
}
|
||||
included_platforms = set(
|
||||
policy.conditions.platform_conditions.include_platforms
|
||||
)
|
||||
excluded_platforms = set(
|
||||
policy.conditions.platform_conditions.exclude_platforms
|
||||
)
|
||||
|
||||
targets_mobile_platforms = (
|
||||
"all" in included_platforms
|
||||
@@ -102,10 +85,10 @@ class entra_conditional_access_policy_approved_client_app_required_for_mobile(Ch
|
||||
)
|
||||
if policy.state == ConditionalAccessPolicyState.ENABLED_FOR_REPORTING:
|
||||
report.status = "FAIL"
|
||||
report.status_extended = f"Conditional Access Policy '{policy.display_name}' reports the requirement of approved client apps or app protection for mobile devices but does not enforce it."
|
||||
report.status_extended = f"Conditional Access Policy {policy.display_name} reports the requirement of approved client apps or app protection for mobile devices but does not enforce it."
|
||||
else:
|
||||
report.status = "PASS"
|
||||
report.status_extended = f"Conditional Access Policy '{policy.display_name}' requires approved client apps or app protection for mobile devices."
|
||||
report.status_extended = f"Conditional Access Policy {policy.display_name} requires approved client apps or app protection for mobile devices."
|
||||
break
|
||||
|
||||
findings.append(report)
|
||||
|
||||
+4
-10
@@ -47,18 +47,12 @@ class entra_conditional_access_policy_block_unknown_device_platforms(Check):
|
||||
if not policy.conditions.platform_conditions:
|
||||
continue
|
||||
|
||||
included_platforms = {
|
||||
(getattr(p, "value", p) or "").lower()
|
||||
for p in policy.conditions.platform_conditions.include_platforms
|
||||
}
|
||||
if "all" not in included_platforms:
|
||||
if "all" not in policy.conditions.platform_conditions.include_platforms:
|
||||
continue
|
||||
|
||||
excluded_platforms = {
|
||||
(getattr(p, "value", p) or "").lower()
|
||||
for p in policy.conditions.platform_conditions.exclude_platforms
|
||||
}
|
||||
if not self.KNOWN_PLATFORMS.issubset(excluded_platforms):
|
||||
if not self.KNOWN_PLATFORMS.issubset(
|
||||
set(policy.conditions.platform_conditions.exclude_platforms)
|
||||
):
|
||||
continue
|
||||
|
||||
if (
|
||||
|
||||
@@ -9,7 +9,7 @@ from msgraph.generated.models.o_data_errors.o_data_error import ODataError
|
||||
from msgraph.generated.security.microsoft_graph_security_run_hunting_query.run_hunting_query_post_request_body import (
|
||||
RunHuntingQueryPostRequestBody,
|
||||
)
|
||||
from pydantic.v1 import BaseModel
|
||||
from pydantic.v1 import BaseModel, validator
|
||||
|
||||
from prowler.lib.logger import logger
|
||||
from prowler.providers.m365.lib.service.service import M365Service
|
||||
@@ -1172,6 +1172,20 @@ class PlatformConditions(BaseModel):
|
||||
include_platforms: List[str] = []
|
||||
exclude_platforms: List[str] = []
|
||||
|
||||
@validator("include_platforms", "exclude_platforms", pre=True)
|
||||
@classmethod
|
||||
def normalize_platforms(cls, values):
|
||||
if not values:
|
||||
return []
|
||||
|
||||
normalized = []
|
||||
for platform in values:
|
||||
value = getattr(platform, "value", platform)
|
||||
if isinstance(value, str) and value:
|
||||
normalized.append(value.lower())
|
||||
|
||||
return normalized
|
||||
|
||||
|
||||
class TransferMethod(Enum):
|
||||
"""Transfer methods for authentication flows in Conditional Access policies."""
|
||||
|
||||
+6
-6
@@ -222,7 +222,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{display_name}' reports the requirement of approved client apps or app protection for mobile devices but does not enforce it."
|
||||
== f"Conditional Access Policy {display_name} reports the requirement of approved client apps or app protection for mobile devices but does not enforce it."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
@@ -312,7 +312,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{display_name}' requires approved client apps or app protection for mobile devices."
|
||||
== f"Conditional Access Policy {display_name} requires approved client apps or app protection for mobile devices."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
@@ -738,7 +738,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{display_name}' requires approved client apps or app protection for mobile devices."
|
||||
== f"Conditional Access Policy {display_name} requires approved client apps or app protection for mobile devices."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
@@ -827,7 +827,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{display_name}' requires approved client apps or app protection for mobile devices."
|
||||
== f"Conditional Access Policy {display_name} requires approved client apps or app protection for mobile devices."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
@@ -963,7 +963,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{enabled_name}' requires approved client apps or app protection for mobile devices."
|
||||
== f"Conditional Access Policy {enabled_name} requires approved client apps or app protection for mobile devices."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
@@ -1052,7 +1052,7 @@ class Test_entra_conditional_access_policy_approved_client_app_required_for_mobi
|
||||
assert result[0].status == "PASS"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== f"Conditional Access Policy '{display_name}' requires approved client apps or app protection for mobile devices."
|
||||
== f"Conditional Access Policy {display_name} requires approved client apps or app protection for mobile devices."
|
||||
)
|
||||
assert (
|
||||
result[0].resource
|
||||
|
||||
Reference in New Issue
Block a user