mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-11-08 20:33:41 +00:00
chore(revision): add missing changes
This commit is contained in:
37 files changed
+640
-147
No files matched your search
+12
@@ -31,6 +31,7 @@ class Test_entra_authentication_method_authenticator_show_context:
|
||||
def test_both_enabled(self):
|
||||
result = self._run(
|
||||
AuthenticationMethodsPolicySettings(
|
||||
authenticator_state="enabled",
|
||||
authenticator_display_app_information_state="enabled",
|
||||
authenticator_display_location_information_state="enabled",
|
||||
)
|
||||
@@ -40,8 +41,19 @@ class Test_entra_authentication_method_authenticator_show_context:
|
||||
def test_location_disabled(self):
|
||||
result = self._run(
|
||||
AuthenticationMethodsPolicySettings(
|
||||
authenticator_state="enabled",
|
||||
authenticator_display_app_information_state="enabled",
|
||||
authenticator_display_location_information_state="disabled",
|
||||
)
|
||||
)
|
||||
assert result[0].status == "FAIL"
|
||||
|
||||
def test_context_enabled_but_authenticator_disabled(self):
|
||||
result = self._run(
|
||||
AuthenticationMethodsPolicySettings(
|
||||
authenticator_state="disabled",
|
||||
authenticator_display_app_information_state="enabled",
|
||||
authenticator_display_location_information_state="enabled",
|
||||
)
|
||||
)
|
||||
assert result[0].status == "FAIL"
|
||||
+36
@@ -101,3 +101,39 @@ class Test_entra_authentication_method_email_otp_disabled:
|
||||
result[0].status_extended
|
||||
== "Email OTP authentication method is disabled in the tenant."
|
||||
)
|
||||
|
||||
def test_email_otp_unknown_state(self):
|
||||
entra_client = mock.MagicMock
|
||||
|
||||
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_authentication_method_email_otp_disabled.entra_authentication_method_email_otp_disabled.entra_client",
|
||||
new=entra_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.entra.entra_authentication_method_email_otp_disabled.entra_authentication_method_email_otp_disabled import (
|
||||
entra_authentication_method_email_otp_disabled,
|
||||
)
|
||||
|
||||
entra_client.authentication_method_configurations = {
|
||||
"Email": AuthenticationMethodConfiguration(
|
||||
id="Email",
|
||||
state="unknown",
|
||||
),
|
||||
}
|
||||
entra_client.tenant_domain = DOMAIN
|
||||
|
||||
check = entra_authentication_method_email_otp_disabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert (
|
||||
result[0].status_extended
|
||||
== "Email OTP authentication method state could not be determined; "
|
||||
"treating as enabled/non-compliant."
|
||||
)
|
||||
+1
-2
@@ -25,8 +25,7 @@ class Test_entra_conditional_access_trusted_named_location_exists:
|
||||
|
||||
def test_no_locations(self):
|
||||
result = self._run([])
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert len(result) == 0
|
||||
|
||||
def test_trusted_ip_location(self):
|
||||
result = self._run(
|
||||
|
||||
+9
@@ -41,6 +41,15 @@ class Test_entra_device_registration_registering_user_not_local_admin:
|
||||
assert result[0].status == "FAIL"
|
||||
|
||||
def test_selected_registering_users(self):
|
||||
result = self._run(
|
||||
DeviceRegistrationPolicy(
|
||||
azure_ad_join_registering_users_type=DeviceRegistrationMembershipType.ENUMERATED.value
|
||||
)
|
||||
)
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "PASS"
|
||||
|
||||
def test_none_registering_users(self):
|
||||
result = self._run(
|
||||
DeviceRegistrationPolicy(
|
||||
azure_ad_join_registering_users_type=DeviceRegistrationMembershipType.NONE.value
|
||||
|
||||
+2
-3
@@ -10,7 +10,7 @@ CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_password_protec
|
||||
|
||||
class Test_entra_password_protection_custom_banned_list_enforced:
|
||||
def _run(self, directory_settings):
|
||||
entra_client = mock.MagicMock
|
||||
entra_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
@@ -27,8 +27,7 @@ class Test_entra_password_protection_custom_banned_list_enforced:
|
||||
|
||||
def test_template_absent(self):
|
||||
result = self._run({})
|
||||
assert len(result) == 1
|
||||
assert result[0].status == "FAIL"
|
||||
assert len(result) == 0
|
||||
|
||||
def test_enforced_with_list(self):
|
||||
result = self._run(
|
||||
|
||||
+2
-2
@@ -10,7 +10,7 @@ CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_password_protec
|
||||
|
||||
class Test_entra_password_protection_lockout_duration_configured:
|
||||
def _run(self, directory_settings):
|
||||
entra_client = mock.MagicMock
|
||||
entra_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
@@ -26,7 +26,7 @@ class Test_entra_password_protection_lockout_duration_configured:
|
||||
return entra_password_protection_lockout_duration_configured().execute()
|
||||
|
||||
def test_template_absent(self):
|
||||
assert self._run({})[0].status == "FAIL"
|
||||
assert len(self._run({})) == 0
|
||||
|
||||
def test_at_minimum(self):
|
||||
result = self._run(
|
||||
|
||||
+1
-1
@@ -26,7 +26,7 @@ class Test_entra_password_protection_lockout_threshold_limited:
|
||||
return entra_password_protection_lockout_threshold_limited().execute()
|
||||
|
||||
def test_template_absent(self):
|
||||
assert self._run({})[0].status == "FAIL"
|
||||
assert len(self._run({})) == 0
|
||||
|
||||
def test_within_limit(self):
|
||||
result = self._run(
|
||||
|
||||
+3
-2
@@ -25,8 +25,9 @@ class Test_entra_password_protection_on_premises_enforced:
|
||||
entra_client.directory_settings = directory_settings
|
||||
return entra_password_protection_on_premises_enforced().execute()
|
||||
|
||||
def test_template_absent(self):
|
||||
assert self._run({})[0].status == "FAIL"
|
||||
def test_no_resources(self):
|
||||
result = self._run({})
|
||||
assert len(result) == 0
|
||||
|
||||
def test_enabled_and_enforced(self):
|
||||
result = self._run(
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@ CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_pim_global_admi
|
||||
|
||||
class Test_entra_pim_global_administrator_approval_required:
|
||||
def _run(self, settings):
|
||||
entra_client = mock.MagicMock
|
||||
entra_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_policy_default_
|
||||
|
||||
class Test_entra_policy_default_user_cannot_create_m365_groups:
|
||||
def _run(self, directory_settings):
|
||||
entra_client = mock.MagicMock
|
||||
entra_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
|
||||
+10
-3
@@ -1,8 +1,6 @@
|
||||
from unittest import mock
|
||||
|
||||
from prowler.providers.m365.services.entra.entra_service import (
|
||||
B2BCollaborationPolicy,
|
||||
)
|
||||
from prowler.providers.m365.services.entra.entra_service import B2BCollaborationPolicy
|
||||
from tests.providers.m365.m365_fixtures import set_mocked_m365_provider
|
||||
|
||||
CHECK_MODULE_PATH = "prowler.providers.m365.services.entra.entra_policy_guest_invitations_restricted_to_allowed_domains.entra_policy_guest_invitations_restricted_to_allowed_domains"
|
||||
@@ -47,3 +45,12 @@ class Test_entra_policy_guest_invitations_restricted_to_allowed_domains:
|
||||
)
|
||||
)
|
||||
assert result[0].status == "FAIL"
|
||||
|
||||
def test_restricted_with_empty_allowed_domains(self):
|
||||
result = self._run(
|
||||
B2BCollaborationPolicy(
|
||||
invitations_restricted_to_allowed_domains=True,
|
||||
allowed_domains=[],
|
||||
)
|
||||
)
|
||||
assert result[0].status == "FAIL"
|
||||
@@ -1,5 +1,6 @@
|
||||
import asyncio
|
||||
import importlib
|
||||
import json
|
||||
from datetime import datetime, timezone
|
||||
from types import SimpleNamespace
|
||||
from unittest.mock import AsyncMock, MagicMock, patch
|
||||
@@ -1196,3 +1197,62 @@ class Test_Entra_Service:
|
||||
queried_users = {call.args[0] for call in by_user_id.call_args_list}
|
||||
assert queried_users == {deleted_user, live_user}
|
||||
assert user_builders[deleted_user].get.await_count == 1
|
||||
|
||||
def test__get_named_locations_paginates_through_next_links(self):
|
||||
entra_service = Entra.__new__(Entra)
|
||||
|
||||
page_one = json.dumps(
|
||||
{
|
||||
"value": [
|
||||
{
|
||||
"@odata.type": "#microsoft.graph.ipNamedLocation",
|
||||
"id": "loc-1",
|
||||
"displayName": "Trusted IPs",
|
||||
"isTrusted": True,
|
||||
"ipRanges": [{"cidrAddress": "10.0.0.0/8"}],
|
||||
}
|
||||
],
|
||||
"@odata.nextLink": "next-link",
|
||||
}
|
||||
)
|
||||
page_two = json.dumps(
|
||||
{
|
||||
"value": [
|
||||
{
|
||||
"@odata.type": "#microsoft.graph.countryNamedLocation",
|
||||
"id": "loc-2",
|
||||
"displayName": "Countries",
|
||||
"isTrusted": False,
|
||||
}
|
||||
]
|
||||
}
|
||||
)
|
||||
|
||||
send_mock = AsyncMock(side_effect=[page_one, page_two])
|
||||
next_link_builder = SimpleNamespace(
|
||||
to_get_request_information=MagicMock(return_value="req-info-page-two")
|
||||
)
|
||||
with_url_mock = MagicMock(return_value=next_link_builder)
|
||||
named_locations_builder = SimpleNamespace(
|
||||
to_get_request_information=MagicMock(return_value="req-info-page-one"),
|
||||
with_url=with_url_mock,
|
||||
)
|
||||
entra_service.client = SimpleNamespace(
|
||||
identity=SimpleNamespace(
|
||||
conditional_access=SimpleNamespace(
|
||||
named_locations=named_locations_builder
|
||||
)
|
||||
),
|
||||
request_adapter=SimpleNamespace(send_primitive_async=send_mock),
|
||||
)
|
||||
|
||||
named_locations = asyncio.run(entra_service._get_named_locations())
|
||||
|
||||
# Both pages are requested and every entry is accumulated before parsing.
|
||||
assert send_mock.await_count == 2
|
||||
with_url_mock.assert_called_once_with("next-link")
|
||||
assert [loc.id for loc in named_locations] == ["loc-1", "loc-2"]
|
||||
assert named_locations[0].is_ip_location is True
|
||||
assert named_locations[0].ip_ranges_count == 1
|
||||
assert named_locations[1].is_ip_location is False
|
||||
assert named_locations[1].is_trusted is False
|
||||
+1
-1
@@ -10,7 +10,7 @@ CHECK_MODULE_PATH = "prowler.providers.m365.services.intune.intune_device_enroll
|
||||
|
||||
class Test_intune_device_enrollment_personal_device_restricted:
|
||||
def _run(self, configurations):
|
||||
intune_client = mock.MagicMock
|
||||
intune_client = mock.MagicMock()
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
|
||||
@@ -161,6 +161,64 @@ class Test_Intune_DeviceEnrollmentConfigurations:
|
||||
def test_empty_response(self):
|
||||
assert self._run_getter({"value": []}) == []
|
||||
|
||||
def test_follows_pagination_across_pages(self):
|
||||
import json
|
||||
|
||||
first_page = {
|
||||
"value": [
|
||||
{
|
||||
"@odata.type": "#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration",
|
||||
"id": "page-one",
|
||||
"priority": 0,
|
||||
"iosRestriction": {
|
||||
"personalDeviceEnrollmentBlocked": True,
|
||||
"platformBlocked": False,
|
||||
},
|
||||
},
|
||||
],
|
||||
"@odata.nextLink": "https://graph.microsoft.com/beta/deviceManagement/deviceEnrollmentConfigurations?$skiptoken=abc",
|
||||
}
|
||||
second_page = {
|
||||
"value": [
|
||||
{
|
||||
"@odata.type": "#microsoft.graph.deviceEnrollmentPlatformRestrictionsConfiguration",
|
||||
"id": "page-two",
|
||||
"priority": 1,
|
||||
"androidRestriction": {
|
||||
"personalDeviceEnrollmentBlocked": False,
|
||||
"platformBlocked": True,
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
|
||||
service = Intune.__new__(Intune)
|
||||
client = mock.MagicMock()
|
||||
builder = (
|
||||
client.device_management.device_enrollment_configurations.with_url.return_value
|
||||
)
|
||||
builder.to_get_request_information.return_value = mock.MagicMock()
|
||||
client.request_adapter.send_primitive_async = AsyncMock(
|
||||
side_effect=[
|
||||
json.dumps(first_page).encode(),
|
||||
json.dumps(second_page).encode(),
|
||||
]
|
||||
)
|
||||
service.client = client
|
||||
|
||||
loop = asyncio.new_event_loop()
|
||||
try:
|
||||
result = loop.run_until_complete(
|
||||
service._get_device_enrollment_configurations()
|
||||
)
|
||||
finally:
|
||||
loop.close()
|
||||
|
||||
# Configurations from BOTH pages must be collected.
|
||||
assert len(result) == 2
|
||||
assert {config.id for config in result} == {"page-one", "page-two"}
|
||||
assert client.request_adapter.send_primitive_async.await_count == 2
|
||||
|
||||
|
||||
class Test_Intune_Service:
|
||||
def test_get_settings_secure_by_default_true(self):
|
||||
|
||||
Reference in new issue
Block a user