Back to Checks
m365

Admin portals are accessible only to administrative roles

entra_admin_portals_access_restriction
Service: entraSeverity: medium
OfficialBuilt-inVerified
Categories:identity-accesse3
Resource Type:NotDefined

Microsoft Entra Conditional Access restricts MicrosoftAdminPortals by targeting admin portals, including all users, excluding administrative roles, and applying a block decision. The assessment determines whether an active policy enforces this restriction rather than only reporting.

Risk

Absent this control, non-admin identities can reach admin portals, jeopardizing integrity (unauthorized tenant changes), confidentiality (exposure of settings and data), and availability (disabling services). Threats include privilege escalation, weakening policies, and creating persistence.

Run this check with Prowler

Run in Prowler Cloud
Run
prowler m365 --checks entra_admin_portals_access_restriction

Recommendation

Enforce least privilege with Conditional Access that blocks MicrosoftAdminPortals for everyone except approved admin roles. Add defense in depth: require strong MFA/authentication strength, compliant devices, and trusted locations; use JIT via PIM. Review role assignments and policies routinely.

Remediation

CLI

New-MgIdentityConditionalAccessPolicy -BodyParameter @{displayName="<example_resource_name>";state="enabled";conditions=@{users=@{includeUsers=@("All");excludeRoles=@("62e90394-69f5-4237-9190-012177145e10")};applications=@{includeApplications=@("MicrosoftAdminPortals")}};grantControls=@{builtInControls=@("block")}}

Terraform

resource "azuread_conditional_access_policy" "<example_resource_name>" {
  display_name = "<example_resource_name>"
  state        = "enabled" # Critical: policy must be enabled to PASS

  conditions {
    users {
      include_users = ["All"] # Critical: include all users
      exclude_roles = ["62e90394-69f5-4237-9190-012177145e10"] # Critical: exclude admin role(s) so only admins can access
    }
    applications {
      included_applications = ["MicrosoftAdminPortals"] # Critical: target Microsoft Admin Portals
    }
  }

  grant_controls {
    built_in_controls = ["block"] # Critical: block non-excluded users
  }
}

Other

1Go to Microsoft Entra admin center > Protection > Conditional Access > Policies > New policy
2Users: Include = All users; Exclude = Directory roles, select all administrative roles
3Target resources: Cloud apps > Select apps > choose Microsoft Admin Portals > Select
4Grant: Block access > Select
5Enable policy: On > Create

Check Code

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_portals_access_restriction(Check):
    """Check if Conditional Access policies deny access to the Microsoft 365 admin center for users with limited access roles.

    This check ensures that Conditional Access policies are in place to deny access to the Microsoft 365 admin center for users with limited access roles.
    """

    def execute(self) -> list[CheckReportM365]:
        """Execute the check to ensure that Conditional Access policies deny access to the Microsoft 365 admin center for users with limited access roles.

        Returns:
            list[CheckReportM365]: A list containing the results 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 limits Entra Admin Center access to administrative roles."

        for policy in entra_client.conditional_access_policies.values():
            if policy.state == ConditionalAccessPolicyState.DISABLED:
                continue

            if not (
                {
                    role for role in policy.conditions.user_conditions.excluded_roles
                }.issubset({admin_role.value for admin_role in AdminRoles})
                and "All" in policy.conditions.user_conditions.included_users
            ):
                continue

            if (
                "MicrosoftAdminPortals"
                not in policy.conditions.application_conditions.included_applications
            ):
                continue

            if (
                ConditionalAccessGrantControl.BLOCK
                in policy.grant_controls.built_in_controls
            ):
                report = CheckReportM365(
                    metadata=self.metadata(),
                    resource=policy,
                    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}' reports Entra Admin Center access to administrative roles but does not limit it."
                else:
                    report.status = "PASS"
                    report.status_extended = f"Conditional Access Policy '{policy.display_name}' limits Entra Admin Center access to administrative roles."
                    break

        findings.append(report)

        return findings