Zero Trust is three principles: verify explicitly, use least-privilege access, and assume breach. On Microsoft Entra ID, those translate directly into Conditional Access (CA) policies and Privileged Identity Management (PIM). This guide builds a defensible baseline you can ship to production.
The Conditional Access mental model
Every sign-in is evaluated against your CA policies. A policy is if (signals) then (grant/block with controls):
- Signals (assignments): users/groups, target apps, locations, device platform/state, client app, sign-in & user risk.
- Decision (access controls): block, or grant with require-MFA, require-compliant-device, require-app-protection, etc.
The golden rules: start in report-only, always exclude a break-glass account, and layer narrow policies rather than one mega-policy.
Step 0 — Break-glass accounts (do this first)
Create two cloud-only *.onmicrosoft.com global admin accounts with long random passwords, excluded from every CA policy, monitored by an alert. They are your way back in if a CA policy locks everyone out.
Step 1 — Named locations
Define trusted egress IPs (offices, VPN) so policies can treat “outside known networks” as higher risk.
Entra admin center → Protection → Conditional Access → Named locations
+ IP ranges location: "Corp Egress" → 203.0.113.0/24 (Mark as trusted)
+ Country location: "Allowed Countries" → your operating countries
Step 2 — The baseline policy set
Build these as separate policies (each in report-only first, then On):
CA01 — Require MFA for all users
- Assignments: All users (exclude break-glass); All cloud apps.
- Grant: Require multifactor authentication.
CA02 — Block legacy authentication
- Assignments: All users; All apps; Client apps = Exchange ActiveSync + Other clients.
- Grant: Block. (Legacy auth can’t do MFA — this closes the biggest hole.)
CA03 — Require compliant or hybrid-joined device for admins
- Assignments: members of “Azure Admins” group; All apps.
- Grant: Require device to be marked compliant OR Hybrid Entra joined.
CA04 — Risk-based (requires Entra ID P2)
- Sign-in risk High → Block; Medium → Require MFA.
- User risk High → Require secure password change.
CA05 — Require app protection policy on mobile
- Device platforms = iOS/Android; Grant: Require approved client app + app protection policy (Intune MAM).
Create CA01 via Microsoft Graph PowerShell
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess","Policy.Read.All"
$params = @{
displayName = "CA01 - Require MFA for all users"
state = "enabledForReportingButNotEnforced" # report-only first
conditions = @{
users = @{ includeUsers = @("All"); excludeUsers = @("<break-glass-object-id>") }
applications = @{ includeApplications = @("All") }
}
grantControls = @{ operator = "OR"; builtInControls = @("mfa") }
}
New-MgIdentityConditionalAccessPolicy -BodyParameter $params
Run report-only for 1–2 weeks, review Insights & reporting for would-be impact, then flip state to enabled.
Step 3 — Least privilege with PIM
Standing global admins are the #1 audit finding. PIM makes privileged roles eligible instead of active: an engineer activates a role just-in-time, with MFA, justification, approval, and a time limit.
Configure a role (e.g., Global Administrator):
Entra admin center → Identity Governance → PIM → Entra roles → Roles → Global Administrator
Role settings:
Activation max duration: 2 hours
Require MFA on activation: Yes
Require justification: Yes
Require approval to activate: Yes → approvers: "Security Leads"
Require ticket information: Yes
Assignments:
Add "Platform Engineers" as ELIGIBLE (not Active)
Activate JIT (self-service):
PIM → My roles → Entra roles → Global Administrator → Activate
duration: 1h · justification: "INC-4821 firewall rule" · (MFA challenge) → pending approval
Now your tenant can have zero standing global admins. Access is granted for exactly as long as the work takes, fully logged.
Step 4 — Access reviews
Schedule quarterly access reviews on privileged roles and high-value groups so eligibility doesn’t rot:
Identity Governance → Access reviews → New
Review: PIM eligible "Global Administrator"
Reviewers: role's managers / Security Leads
Recurrence: Quarterly · Auto-apply results: Yes · If no response: Remove access
Step 5 — Verify & monitor
- Sign-in logs → filter by Conditional Access to confirm policies apply as designed.
- Audit logs → PIM activations, approvals, role assignments.
- Stream both to Log Analytics / Microsoft Sentinel and alert on: break-glass sign-in, PIM activation of Global Admin, CA policy modification.
Rollout checklist
Enterprise scenario
A platform team rolled out PIM and set Require approval to activate on Global Administrator with “Security Leads” as approvers. Two weeks later, a Sev1 hit at 02:00: Exchange Online routing was broken, the on-call SRE needed Global Admin, and every approver was asleep. Activation sat in PendingApproval for 40 minutes. The post-incident finding was blunt: they had traded standing access for an availability dependency on a human.
The fix was to stop putting break-glass and emergency paths through the approval gate. We kept approval on the eligible day-to-day assignment but created a separate, alert-wired emergency path: a dedicated cloud-only account holding the role as Active assignment in PIM (no activation step), excluded from CA, with a Sentinel analytics rule firing on any sign-in.
The subtle gotcha is the PIM activation hierarchy: a role can be eligible and active simultaneously, and Active assignments bypass activation controls entirely — including approval and MFA-on-activation (the account still hits MFA via CA). We also dropped the auth-context requirement on the break-glass exclusion so a misconfigured policy couldn’t strand it.
# Emergency: permanent Active assignment, no approval gate
$params = @{
action = "adminAssign"
accessId = "member"
principalId = "<break-glass-object-id>"
roleDefinitionId = "62e90394-69f5-4237-9190-012177145e10" # Global Administrator
directoryScopeId = "/"
scheduleInfo = @{ startDateTime = (Get-Date); expiration = @{ type = "noExpiration" } }
}
New-MgRoleManagementDirectoryRoleAssignmentScheduleRequest -BodyParameter $params
The principle held — zero standing admins for humans doing normal work — without making 02:00 recovery depend on someone answering their phone.
Common pitfalls
- Locking yourself out — always report-only first, always exclude break-glass.
- Forgetting service accounts — workload identities need their own CA strategy (Conditional Access for workload identities, P2).
- One giant policy — layered, single-purpose policies are far easier to reason about and audit.
Zero Trust isn’t a product you buy — it’s the steady removal of implicit trust. Conditional Access verifies every request; PIM ensures privilege is temporary. Together they cover “verify explicitly” and “least privilege”; pair them with device compliance (Intune) and network segmentation (your landing zone) for “assume breach.”