This is the baseline from our Conditional Access framework article as something you can actually use: ten policies in Microsoft Graph JSON, a script that imports them into your tenant in report-only mode, and the order in which to switch them on. Free, no email required. Download the JSON library
What is in the file
| Policy | Users | Control | Licence |
|---|---|---|---|
| CA001-AllUsers-AllApps-LegacyAuth-Block | All (excl. break-glass) | Block | P1 |
| CA002-Admins-AllApps-AnyPlatform-PhishingResistantMFA | 14 privileged roles | Authentication strength: phishing-resistant | P1 |
| CA003-AllUsers-AllApps-AnyPlatform-RequireMFA | All (excl. break-glass, service accounts) | MFA | P1 |
| CA004-AllUsers-M365-AnyPlatform-RequireCompliantDevice | All members | Compliant device or Entra hybrid joined | P1 + Intune |
| CA005-AllUsers-AllApps-UnsupportedPlatforms-Block | All | Block Linux/other, ChromeOS optional | P1 |
| CA006-AllUsers-AdminPortals-AnyPlatform-RequireMFA | All | MFA + sign-in frequency 1 hour | P1 |
| CA007-Guests-AllApps-AnyPlatform-MFA-LimitedApps | Guests and external | MFA; Office 365 only | P1 |
| CA008-AllUsers-AllApps-HighRisk-Block | All | Block on high user or sign-in risk; MFA on medium | P2 |
| CA009-AllUsers-AllApps-BlockedCountries-Block | All (excl. travel group) | Block named location "Blocked countries" | P1 |
| CA010-AllUsers-M365-UnmanagedDevice-BrowserOnly | All | App-enforced restrictions; no download | P1 |
Import in report-only mode
Every policy in the file has "state": "enabledForReportingButNotEnforced". Nothing changes for your users until you flip a policy to enabled. You need the Conditional Access Administrator role and the Graph PowerShell SDK; sign in interactively in a browser.
Connect-MgGraph -Scopes "Policy.ReadWrite.ConditionalAccess","Policy.Read.All","Application.Read.All"
$lib = Get-Content .\conditional-access-baseline.json -Raw | ConvertFrom-Json
foreach ($p in $lib.policies) {
$body = $p | ConvertTo-Json -Depth 20
Invoke-MgGraphRequest -Method POST -Uri "https://graph.microsoft.com/v1.0/identity/conditionalAccess/policies" -Body $body -ContentType "application/json"
Write-Host "Created (report-only):" $p.displayName
}
Before you run it, replace the three placeholders in the file: the break-glass group id, the named location id for blocked countries, and (for CA002) your admin roles if you have customised them. The README block at the top of the JSON lists all three.
The order to enable them
- CA001 (legacy auth) — after seven days report-only with zero legitimate hits.
- CA002 (admins) — the day your admins have FIDO2 keys or passkeys registered.
- CA006 (admin portals) — same day as CA002.
- CA003 (MFA everyone) — after the registration campaign hits 95%.
- CA009 (countries) and CA005 (platforms) — low impact, enable together.
- CA007 (guests) — after telling the three partners who will notice.
- CA004 (compliant device) — only after Intune compliance is above 90%; this is the one that locks people out if you rush it.
- CA010 (unmanaged browser-only) — the week after CA004.
- CA008 (risk) — if you have P2; otherwise delete it.
We deploy exactly this library, tuned to your tenant and with the rollout managed, in the Microsoft 365 Hardening Sprint. If you use the free version and get stuck, the contact form works too.