mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-10-03 17:54:05 +00:00
fix(m365): skip defender preset policies without rules (#12809)
(cherry picked from commit 61ef44a03b)
This commit is contained in:
@@ -0,0 +1 @@
|
||||
`KeyError` in M365 Defender malware, anti-phishing and inbound anti-spam checks when the tenant has Standard or Strict preset security policies
|
||||
+6
@@ -55,6 +55,12 @@ class defender_antiphishing_policy_configured(Check):
|
||||
policy_name,
|
||||
policy,
|
||||
) in defender_client.antiphishing_policies.items():
|
||||
# Preset security policies are scoped by protection policy rules, not filter rules
|
||||
if (
|
||||
not policy.default
|
||||
and policy.name not in defender_client.antiphishing_rules
|
||||
):
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
|
||||
+6
@@ -51,6 +51,12 @@ class defender_antispam_policy_inbound_no_allowed_domains(Check):
|
||||
default_policy_well_configured = False
|
||||
|
||||
for policy in defender_client.inbound_spam_policies:
|
||||
# Preset security policies are scoped by protection policy rules, not filter rules
|
||||
if (
|
||||
not policy.default
|
||||
and policy.identity not in defender_client.inbound_spam_rules
|
||||
):
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
|
||||
+6
@@ -51,6 +51,12 @@ class defender_malware_policy_common_attachments_filter_enabled(Check):
|
||||
default_policy_well_configured = False
|
||||
|
||||
for policy in defender_client.malware_policies:
|
||||
# Preset security policies are scoped by protection policy rules, not filter rules
|
||||
if (
|
||||
not policy.is_default
|
||||
and policy.identity not in defender_client.malware_rules
|
||||
):
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
|
||||
+6
@@ -114,6 +114,12 @@ class defender_malware_policy_comprehensive_attachments_filter_applied(Check):
|
||||
default_policy_well_configured = False
|
||||
|
||||
for policy in defender_client.malware_policies:
|
||||
# Preset security policies are scoped by protection policy rules, not filter rules
|
||||
if (
|
||||
not policy.is_default
|
||||
and policy.identity not in defender_client.malware_rules
|
||||
):
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
|
||||
+6
@@ -51,6 +51,12 @@ class defender_malware_policy_notifications_internal_users_malware_enabled(Check
|
||||
default_policy_well_configured = False
|
||||
|
||||
for policy in defender_client.malware_policies:
|
||||
# Preset security policies are scoped by protection policy rules, not filter rules
|
||||
if (
|
||||
not policy.is_default
|
||||
and policy.identity not in defender_client.malware_rules
|
||||
):
|
||||
continue
|
||||
report = CheckReportM365(
|
||||
metadata=self.metadata(),
|
||||
resource=policy,
|
||||
|
||||
+83
@@ -521,3 +521,86 @@ class Test_defender_antiphishing_policy_configured:
|
||||
check = defender_antiphishing_policy_configured()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_preset_policy_without_rule_is_skipped(self):
|
||||
defender_client = mock.MagicMock()
|
||||
defender_client.audited_tenant = "audited_tenant"
|
||||
defender_client.audited_domain = DOMAIN
|
||||
defender_client.audit_config = {}
|
||||
|
||||
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.defender.defender_antiphishing_policy_configured.defender_antiphishing_policy_configured.defender_client",
|
||||
new=defender_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.defender.defender_antiphishing_policy_configured.defender_antiphishing_policy_configured import (
|
||||
defender_antiphishing_policy_configured,
|
||||
)
|
||||
from prowler.providers.m365.services.defender.defender_service import (
|
||||
AntiphishingPolicy,
|
||||
AntiphishingRule,
|
||||
)
|
||||
|
||||
defender_client.antiphishing_policies = {
|
||||
"Default": AntiphishingPolicy(
|
||||
name="Default",
|
||||
spoof_intelligence=True,
|
||||
spoof_intelligence_action="Quarantine",
|
||||
dmarc_reject_action="Quarantine",
|
||||
dmarc_quarantine_action="Quarantine",
|
||||
safety_tips=True,
|
||||
unauthenticated_sender_action=True,
|
||||
show_tag=True,
|
||||
honor_dmarc_policy=True,
|
||||
default=True,
|
||||
),
|
||||
"Standard Preset Security Policy1663355404982": AntiphishingPolicy(
|
||||
name="Standard Preset Security Policy1663355404982",
|
||||
spoof_intelligence=True,
|
||||
spoof_intelligence_action="Quarantine",
|
||||
dmarc_reject_action="Quarantine",
|
||||
dmarc_quarantine_action="Quarantine",
|
||||
safety_tips=True,
|
||||
unauthenticated_sender_action=True,
|
||||
show_tag=True,
|
||||
honor_dmarc_policy=True,
|
||||
default=False,
|
||||
),
|
||||
"Custom1": AntiphishingPolicy(
|
||||
name="Custom1",
|
||||
spoof_intelligence=True,
|
||||
spoof_intelligence_action="Quarantine",
|
||||
dmarc_reject_action="Quarantine",
|
||||
dmarc_quarantine_action="Quarantine",
|
||||
safety_tips=True,
|
||||
unauthenticated_sender_action=True,
|
||||
show_tag=True,
|
||||
honor_dmarc_policy=True,
|
||||
default=False,
|
||||
),
|
||||
}
|
||||
defender_client.antiphishing_rules = {
|
||||
"Custom1": AntiphishingRule(
|
||||
state="Enabled",
|
||||
priority=1,
|
||||
users=["user1@example.com"],
|
||||
groups=None,
|
||||
domains=None,
|
||||
)
|
||||
}
|
||||
|
||||
check = defender_antiphishing_policy_configured()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 2
|
||||
assert "Standard Preset Security Policy1663355404982" not in [
|
||||
finding.resource_id for finding in result
|
||||
]
|
||||
|
||||
+62
@@ -410,3 +410,65 @@ class Test_defender_antispam_policy_inbound_no_allowed_domains:
|
||||
check = defender_antispam_policy_inbound_no_allowed_domains()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_preset_policy_without_rule_is_skipped(self):
|
||||
defender_client = mock.MagicMock()
|
||||
defender_client.audited_tenant = "audited_tenant"
|
||||
defender_client.audited_domain = DOMAIN
|
||||
defender_client.audit_config = {}
|
||||
|
||||
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.defender.defender_antispam_policy_inbound_no_allowed_domains.defender_antispam_policy_inbound_no_allowed_domains.defender_client",
|
||||
new=defender_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.defender.defender_antispam_policy_inbound_no_allowed_domains.defender_antispam_policy_inbound_no_allowed_domains import (
|
||||
defender_antispam_policy_inbound_no_allowed_domains,
|
||||
)
|
||||
from prowler.providers.m365.services.defender.defender_service import (
|
||||
DefenderInboundSpamPolicy,
|
||||
InboundSpamRule,
|
||||
)
|
||||
|
||||
defender_client.inbound_spam_policies = [
|
||||
DefenderInboundSpamPolicy(
|
||||
identity="Default",
|
||||
allowed_sender_domains=[],
|
||||
default=True,
|
||||
),
|
||||
DefenderInboundSpamPolicy(
|
||||
identity="Standard Preset Security Policy1663355404982",
|
||||
allowed_sender_domains=[],
|
||||
default=False,
|
||||
),
|
||||
DefenderInboundSpamPolicy(
|
||||
identity="Custom1",
|
||||
allowed_sender_domains=[],
|
||||
default=False,
|
||||
),
|
||||
]
|
||||
defender_client.inbound_spam_rules = {
|
||||
"Custom1": InboundSpamRule(
|
||||
state="Enabled",
|
||||
priority=1,
|
||||
users=["user1@example.com"],
|
||||
groups=None,
|
||||
domains=None,
|
||||
)
|
||||
}
|
||||
|
||||
check = defender_antispam_policy_inbound_no_allowed_domains()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 2
|
||||
assert "Standard Preset Security Policy1663355404982" not in [
|
||||
finding.resource_id for finding in result
|
||||
]
|
||||
|
||||
+74
@@ -442,3 +442,77 @@ class Test_defender_malware_policy_common_attachments_filter_enabled:
|
||||
check = defender_malware_policy_common_attachments_filter_enabled()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_preset_policy_without_rule_is_skipped(self):
|
||||
defender_client = mock.MagicMock()
|
||||
defender_client.audited_tenant = "audited_tenant"
|
||||
defender_client.audited_domain = DOMAIN
|
||||
defender_client.audit_config = {}
|
||||
|
||||
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.defender.defender_malware_policy_common_attachments_filter_enabled.defender_malware_policy_common_attachments_filter_enabled.defender_client",
|
||||
new=defender_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.defender.defender_malware_policy_common_attachments_filter_enabled.defender_malware_policy_common_attachments_filter_enabled import (
|
||||
defender_malware_policy_common_attachments_filter_enabled,
|
||||
)
|
||||
from prowler.providers.m365.services.defender.defender_service import (
|
||||
MalwarePolicy,
|
||||
MalwareRule,
|
||||
)
|
||||
|
||||
defender_client.audit_config = {
|
||||
"recommended_blocked_file_types": ["exe", "bat"]
|
||||
}
|
||||
defender_client.malware_policies = [
|
||||
MalwarePolicy(
|
||||
identity="Default",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=True,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Standard Preset Security Policy1663355404982",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Custom1",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
]
|
||||
defender_client.malware_rules = {
|
||||
"Custom1": MalwareRule(
|
||||
state="Enabled",
|
||||
priority=1,
|
||||
users=["user1@example.com"],
|
||||
groups=None,
|
||||
domains=None,
|
||||
)
|
||||
}
|
||||
|
||||
check = defender_malware_policy_common_attachments_filter_enabled()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 2
|
||||
assert "Standard Preset Security Policy1663355404982" not in [
|
||||
finding.resource_id for finding in result
|
||||
]
|
||||
|
||||
+74
@@ -452,3 +452,77 @@ class Test_defender_malware_policy_comprehensive_attachments_filter_applied:
|
||||
check = defender_malware_policy_comprehensive_attachments_filter_applied()
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_preset_policy_without_rule_is_skipped(self):
|
||||
defender_client = mock.MagicMock()
|
||||
defender_client.audited_tenant = "audited_tenant"
|
||||
defender_client.audited_domain = DOMAIN
|
||||
defender_client.audit_config = {}
|
||||
|
||||
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.defender.defender_malware_policy_comprehensive_attachments_filter_applied.defender_malware_policy_comprehensive_attachments_filter_applied.defender_client",
|
||||
new=defender_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.defender.defender_malware_policy_comprehensive_attachments_filter_applied.defender_malware_policy_comprehensive_attachments_filter_applied import (
|
||||
defender_malware_policy_comprehensive_attachments_filter_applied,
|
||||
)
|
||||
from prowler.providers.m365.services.defender.defender_service import (
|
||||
MalwarePolicy,
|
||||
MalwareRule,
|
||||
)
|
||||
|
||||
defender_client.audit_config = {
|
||||
"recommended_blocked_file_types": ["exe", "bat"]
|
||||
}
|
||||
defender_client.malware_policies = [
|
||||
MalwarePolicy(
|
||||
identity="Default",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=True,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Standard Preset Security Policy1663355404982",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Custom1",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
]
|
||||
defender_client.malware_rules = {
|
||||
"Custom1": MalwareRule(
|
||||
state="Enabled",
|
||||
priority=1,
|
||||
users=["user1@example.com"],
|
||||
groups=None,
|
||||
domains=None,
|
||||
)
|
||||
}
|
||||
|
||||
check = defender_malware_policy_comprehensive_attachments_filter_applied()
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 2
|
||||
assert "Standard Preset Security Policy1663355404982" not in [
|
||||
finding.resource_id for finding in result
|
||||
]
|
||||
|
||||
+76
@@ -456,3 +456,79 @@ class Test_defender_malware_policy_notifications_internal_users_malware_enabled:
|
||||
)
|
||||
result = check.execute()
|
||||
assert len(result) == 0
|
||||
|
||||
def test_preset_policy_without_rule_is_skipped(self):
|
||||
defender_client = mock.MagicMock()
|
||||
defender_client.audited_tenant = "audited_tenant"
|
||||
defender_client.audited_domain = DOMAIN
|
||||
defender_client.audit_config = {}
|
||||
|
||||
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.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled.defender_client",
|
||||
new=defender_client,
|
||||
),
|
||||
):
|
||||
from prowler.providers.m365.services.defender.defender_malware_policy_notifications_internal_users_malware_enabled.defender_malware_policy_notifications_internal_users_malware_enabled import (
|
||||
defender_malware_policy_notifications_internal_users_malware_enabled,
|
||||
)
|
||||
from prowler.providers.m365.services.defender.defender_service import (
|
||||
MalwarePolicy,
|
||||
MalwareRule,
|
||||
)
|
||||
|
||||
defender_client.audit_config = {
|
||||
"recommended_blocked_file_types": ["exe", "bat"]
|
||||
}
|
||||
defender_client.malware_policies = [
|
||||
MalwarePolicy(
|
||||
identity="Default",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=True,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Standard Preset Security Policy1663355404982",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
MalwarePolicy(
|
||||
identity="Custom1",
|
||||
enable_file_filter=True,
|
||||
enable_internal_sender_admin_notifications=True,
|
||||
internal_sender_admin_address="admin@example.com",
|
||||
file_types=["exe", "bat"],
|
||||
is_default=False,
|
||||
),
|
||||
]
|
||||
defender_client.malware_rules = {
|
||||
"Custom1": MalwareRule(
|
||||
state="Enabled",
|
||||
priority=1,
|
||||
users=["user1@example.com"],
|
||||
groups=None,
|
||||
domains=None,
|
||||
)
|
||||
}
|
||||
|
||||
check = (
|
||||
defender_malware_policy_notifications_internal_users_malware_enabled()
|
||||
)
|
||||
result = check.execute()
|
||||
|
||||
assert len(result) == 2
|
||||
assert "Standard Preset Security Policy1663355404982" not in [
|
||||
finding.resource_id for finding in result
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user