fix(m365): require active PIM stale alert before flagging accounts

The PIM alert object exposes an is_active flag that goes False once the
alert condition stops firing, even though the previous number_of_affected_items
count can stick around in the API response. The check was ignoring that
flag, so a tenant whose alert was already resolved or dismissed could
still receive a FAIL based on stale counters.

Gate the FAIL branch on alert.is_active so only currently-firing alerts
produce findings; everything else (resolved alert, inactive with leftover
counts) is reported as PASS. A regression test covers the inactive-with-
counts case to lock the behavior in.
This commit is contained in:
Hugo P.Brito
2026-05-11 11:48:46 +01:00
parent 4cf2207d58
commit b49e49f543
2 changed files with 47 additions and 1 deletions
@@ -40,7 +40,7 @@ class entra_pim_stale_sign_in_alert(Check):
resource_name="PIM Stale Sign-In Alert",
)
if stale_alert.number_of_affected_items > 0:
if stale_alert.is_active and stale_alert.number_of_affected_items > 0:
affected_users = ", ".join(
incident.assignee_display_name or incident.assignee_id
for incident in stale_alert.affected_items[:5]
@@ -202,6 +202,52 @@ class Test_entra_pim_stale_sign_in_alert:
assert result[0].resource_name == "Contoso"
assert result[0].location == "global"
def test_inactive_alert_with_lingering_affected_items(self):
"""PASS: alert reports affected items but is not active."""
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_pim_stale_sign_in_alert.entra_pim_stale_sign_in_alert.entra_client",
new=entra_client,
),
):
from prowler.providers.m365.services.entra.entra_pim_stale_sign_in_alert.entra_pim_stale_sign_in_alert import (
entra_pim_stale_sign_in_alert,
)
entra_client.pim_alerts = {
"DirectoryRole_StaleSignInAlert": PimAlert(
id="alert-resolved",
alert_definition_id="DirectoryRole_StaleSignInAlert",
scope_id="/",
scope_type="DirectoryRole",
is_active=False,
number_of_affected_items=3,
incident_count=3,
affected_items=[
PimAlertIncident(
assignee_display_name="Resolved User",
assignee_id="user-resolved",
role_display_name="Global Administrator",
last_sign_in_date_time="2024-01-01T00:00:00Z",
)
],
)
}
check = entra_pim_stale_sign_in_alert()
result = check.execute()
assert len(result) == 1
assert result[0].status == "PASS"
assert "no stale accounts" in result[0].status_extended
assert result[0].resource_id == "alert-resolved"
def test_empty_pim_alerts_no_organizations(self):
"""No findings when PIM alerts empty and no organizations."""
entra_client = mock.MagicMock()