Back to Checks
m365

All users with administrative roles are cloud-only accounts

entra_admin_users_cloud_only
Service: entraSeverity: high
OfficialBuilt-inVerified
Categories:identity-accesstrust-boundariese3
Resource Type:NotDefined

Microsoft Entra administrative users are evaluated to confirm they are cloud-only accounts, with no on-premises directory synchronization for any user holding privileged roles.

Prowler logoProwlerprowler-provider-m365

Risk

On-premises-synced privileged accounts extend the cloud trust boundary to AD. If AD or the sync channel is compromised, attackers can:

  • Escalate into Entra roles
  • Alter tenant settings and access data
  • Maintain persistence via on-prem credentials

This harms confidentiality and integrity and complicates recovery.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler m365 --checks entra_admin_users_cloud_only

Recommendation

Assign Entra roles only to cloud-native accounts. Enforce least privilege, MFA, and Conditional Access; use PIM for just-in-time elevation. Maintain cloud-only break-glass accounts, perform periodic access reviews, and prohibit synced identities from holding privileged roles for defense in depth.

Remediation

CLI

Remove-MgDirectoryRoleMemberByRef -DirectoryRoleId <example_role_id> -DirectoryObjectId <example_user_object_id>

Other

1In the Microsoft Entra admin center, go to Identity > Users. Filter: On-premises sync enabled = Yes. Identify any users with administrative roles. 2. If needed, create a cloud-only admin: Identity > Users > New user > Create user; under Roles, assign the required admin role. 3. Remove admin roles from synchronized users: Identity > Roles & administrators > select the role > Members > select the synchronized user(s) > Remove.

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


class entra_admin_users_cloud_only(Check):
    """
    Check to ensure that there are no admin accounts with non-cloud-only accounts in Microsoft 365.
    This check verifies if any user with admin roles has an on-premises synchronized account.
    If such users are found, the check will fail.
    """

    def execute(self) -> List[CheckReportM365]:
        """
        Execute the check to identify admin accounts with non-cloud-only accounts.
        Returns:
            List[CheckReportM365]: A list containing the check report with the status and details.
        """
        findings = []
        if entra_client.users:
            non_cloud_admins = []
            for user_id, user in entra_client.users.items():
                for role in user.directory_roles_ids:
                    if (
                        role in {admin_role.value for admin_role in AdminRoles}
                        and user.on_premises_sync_enabled
                    ):
                        non_cloud_admins.append(user_id)

            report = CheckReportM365(
                metadata=self.metadata(),
                resource={},
                resource_name="Cloud-only account",
                resource_id="cloudOnlyAccount",
            )
            report.status = "PASS"
            report.status_extended = (
                "All the users with administrative roles are cloud-only accounts."
            )

            if non_cloud_admins:
                report.status = "FAIL"
                ids_str = ", ".join(non_cloud_admins)
                report.status_extended = f"There are some users with administrative roles that are not cloud-only accounts: {ids_str}"

            findings.append(report)
        return findings