Users in administrative roles require multifactor authentication via a Conditional Access policy for all applications
Microsoft Entra Conditional Access policies that enforce multifactor authentication for users in administrative roles across all resources.
The assessment identifies at least one active policy that targets admin roles (or all users), includes all applications, and grants access only when Require multifactor authentication is satisfied.
Risk
Without enforced MFA on privileged accounts, stolen or phished passwords can grant admin access, enabling tenant takeover. Attackers may exfiltrate data, change configurations, consent malicious apps, and disable protections, impacting confidentiality, integrity, and availability.
Run this check with Prowler
Run in Prowler Cloudprowler m365 --checks entra_admin_users_mfa_enabledRecommendation
Require MFA for all administrative roles with Conditional Access scoped to All cloud apps to avoid gaps. Prefer phishing-resistant methods (FIDO2, passkeys, Authenticator). Apply least privilege, limit exclusions, protect break-glass accounts, monitor sign-ins, and verify policies actively enforce, not just report.
Remediation
CLI
az rest --method post --url https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies --body '{"displayName":"Require MFA for all users","state":"enabled","conditions":{"users":{"includeUsers":["All"]},"applications":{"includeApplications":["All"]}},"grantControls":{"operator":"OR","builtInControls":["mfa"]}}'Terraform
resource "azuread_conditional_access_policy" "<example_resource_name>" {
display_name = "Require MFA for all users"
state = "enabled" # Critical: policy must be enabled to enforce
conditions {
users {
include_users = ["All"] # Critical: applies to all users, covering all admin roles
}
applications {
included_applications = ["All"] # Critical: targets all cloud apps/resources
}
}
grant_controls {
built_in_controls = ["mfa"] # Critical: require multifactor authentication
operator = "OR"
}
}Other
Check Code
from typing import List
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 (
AdminRoles,
ConditionalAccessGrantControl,
ConditionalAccessPolicyState,
)
class entra_admin_users_mfa_enabled(Check):
"""
Ensure multifactor authentication is enabled for all users in administrative roles.
This check verifies that at least one Conditional Access Policy in Microsoft Entra, which is in an enabled state,
applies to administrative roles and enforces multifactor authentication (MFA). Enforcing MFA for privileged accounts
is critical to reduce the risk of unauthorized access through compromised credentials.
The check fails if no enabled policy is found that requires MFA for any administrative role.
"""
def execute(self) -> List[CheckReportM365]:
"""
Execute the admin MFA requirement check for administrative roles.
Iterates over the Conditional Access Policies retrieved from the Entra client and generates a report
indicating whether MFA is enforced for users in administrative roles.
Returns:
List[CheckReportM365]: A list containing a single report with the result 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 requiring MFA for administrative roles was found."
for policy in entra_client.conditional_access_policies.values():
if policy.state == ConditionalAccessPolicyState.DISABLED:
continue
if not ({admin_role.value for admin_role in AdminRoles}).issubset(
set(policy.conditions.user_conditions.included_roles)
):
if "All" not in policy.conditions.user_conditions.included_users:
continue
if (
"All"
not in policy.conditions.application_conditions.included_applications
):
continue
if (
ConditionalAccessGrantControl.MFA
in policy.grant_controls.built_in_controls
):
report = CheckReportM365(
metadata=self.metadata(),
resource=entra_client.conditional_access_policies,
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}' only reports MFA for administrative roles but does not enforce it."
else:
report.status = "PASS"
report.status_extended = f"Conditional Access Policy '{policy.display_name}' enforces MFA for administrative roles."
break
findings.append(report)
return findingsReferences
- https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-getstarted
- https://learn.microsoft.com/en-us/entra/identity/conditional-access/policy-alt-all-users-compliant-hybrid-or-mfa
- https://learn.microsoft.com/en-us/entra/identity/conditional-access/howto-conditional-access-policy-admin-mfa
- https://learn.microsoft.com/en-us/entra/identity/authentication/tutorial-enable-azure-mfa
- https://learn.microsoft.com/en-us/entra/identity/conditional-access/policy-alt-admin-device-compliand-hybrid
- https://learn.microsoft.com/en-us/entra/identity/authentication/howto-mfa-userstates