Verplichte MFA voor Azure fase 2: welke identiteiten vastlopen op Resource Manager
Sinds 1 juli 2026 kan geen enkele tenant fase 2 van de verplichte MFA voor Azure nog verder uitstellen. Elke create, update of delete die een gebruikersaccount naar Azure Resource Manager stuurt, vraagt nu om MFA, ongeacht de client. De tijdlijn is elders al uitgebreid beschreven, dus deze blog gaat over de werking: waar de controle precies plaatsvindt, waarom je Conditional Access-uitsluitingen hier niets uitmaken, welke accounts er meestal op stuklopen en hoe je ze in je logs vindt voordat de eerste deployment faalt.
Foto: Getty Images via Unsplash
Wat er wordt afgedwongen, en waar
https://management.azure.com valt eronder. De client maakt niet uit. Azure CLI, Azure PowerShell, de Azure mobile app, de SDK's, losse REST-calls en IaC-tools (die via de app-ID's van CLI of PowerShell authenticeren) komen allemaal bij hetzelfde endpoint uit.Alleen create, update en delete worden afgedwongen, lezen niet. Dat verklaart waarom veel organisaties na de start van de uitrol dachten dat ze er goed vanaf kwamen: een inventarisatiescript dat alleen
Get-AzResource draait blijft gewoon werken, en de eerste fout komt pas weken later, als iemands deployment draait.Minstens zo nuttig is weten wat er buiten valt. Microsoft Graph valt in het algemeen niet onder de handhaving, omdat alleen
management.azure.com telt; een script dat met een gebruikersaccount Graph aanroept heeft hier geen last van (je eigen Conditional Access is een ander verhaal). Volgens diezelfde definitie vallen data plane-endpoints zoals Key Vault of Storage er ook buiten. Workload identities, dus managed identities en service principals, worden door geen van beide fases geraakt, en het serviceaccount van Entra Connect of Cloud Sync ook niet. In de sovereign clouds wordt op dit moment helemaal niet gehandhaafd.Aan de foutmelding aan de clientkant zie je ook hoe de handhaving is gebouwd. Volgens Microsofts aankondiging van fase 2 loopt de handhaving via Azure Policy, en de FAQ zegt dat Microsoft bij systeemhandhaving dezelfde policy uitrolt die je ook zelf kunt toewijzen. Een geblokkeerde schrijfactie in Azure CLI komt terug als
RequestDisallowedByPolicy met de tekst "Users must authenticate with multi-factor authentication to create or update resources", en dat is letterlijk de naam van de ingebouwde definitie. Daar zijn er twee van: één voor create en update (4e6c27d5-a6ee-49cf-b2b4-d8fe90fa2b8b, Audit of Deny) en één voor delete (db4a9d17-db75-4f46-9fcb-9f9526604417, AuditAction of DenyAction). Met Azure CLI 2.76 of nieuwer en Az PowerShell 14.3 of nieuwer bevat de foutmelding ook meteen een az login --claims-challenge- of Connect-AzAccount -ClaimsChallenge-commando, zodat een interactieve gebruiker kan opschalen naar MFA (zie de troubleshootingpagina van de CLI). Oudere versies geven vagere fouten, en dat is op zich al een goede reden om beheerwerkplekken en build agents bij te werken.Waar ik steeds op terugkom: het deny-effect van Azure Policy beoordeelt create- en update-requests, en denyAction ondersteunt op dit moment alleen delete. POST-acties, zoals de sleutels van een storage account opvragen of een VM herstarten, zijn geen van beide. Ik heb Microsoft nergens zien zeggen of de systeemhandhaving die wel afvangt, dus ik zou er niet op bouwen als gat. Voor mij is het vooral een reden waarom je eigen Conditional Access-policy die MFA eist voor Azure-beheer de echte maatregel blijft, met de platformhandhaving als ondergrens daaronder.
Conditional Access-uitsluitingen en systeemhandhaving
In de praktijk betekent dit dat je lijst met Conditional Access-uitsluitingen nu een lijst met kandidaat-storingen is. Elk account dat ooit "om technische redenen" van MFA is uitgezonderd en iets in Azure aanmaakt, wijzigt of verwijdert, staat erop. Er is geen opt-out, testtenants doen ook mee, en zodra de handhaving voor jouw tenant gestart is, kan alleen een Global Administrator Microsoft Support nog vragen om die tijdelijk op te heffen.
De identiteiten die meestal vastlopen
svc-deploy-account met Contributor op een subscription dat aanmeldt met Connect-AzAccount -Credential of az login -u -p gebruikt de resource owner password credentials-flow (ROPC), en ROPC kan geen MFA. De Learn-pagina noemt ook de SDK-varianten, waaronder DefaultAzureCredential of EnvironmentCredential met AZURE_USERNAME en AZURE_PASSWORD gezet. Die mis je makkelijk, want het zit in applicatiecode die niemand van het identityteam ooit leest. Serviceaccounts die vanuit Active Directory gesynchroniseerd zijn, lopen er op precies dezelfde manier tegenaan.Gedeelde beheeraccounts zijn de volgende groep. Een
azureadmin@-account dat een heel team gebruikt, is meestal uitgezonderd van MFA, of heeft MFA geregistreerd op de telefoon van één persoon, wat een probleem op zich is. Fase 2 dwingt die vraag af, en het goede antwoord is persoonlijke beheeraccounts.Break-glass accounts moeten ook MFA doen. Microsoft raadt daarvoor een passkey (FIDO2) of certificate-based authentication aan, en beide voldoen aan de eis; de richtlijn voor emergency access accounts noemt passkeys inmiddels de aanbevolen methode en CBA voor organisaties die al een PKI hebben. Leunde je noodprocedure op terugvallen naar CLI of PowerShell met een lang wachtwoord, omdat de portal sinds fase 1 al om MFA vroeg, dan is die uitweg nu weg.
Gastbeheerders zijn de laatste groep die ik altijd nakijk: partners en leveranciers met een RBAC-rol op je subscriptions. Voor B2B-gasten moet de MFA óf in jouw tenant gebeuren, óf in hun eigen tenant, waarbij jouw cross-tenant access settings hun MFA-claims vertrouwen. Vertrouw je inkomende MFA niet, dan moeten ze een methode in jouw tenant registreren, en dat regel je makkelijker voordat hun deployment faalt.
De betrokken accounts vinden
Caller toe: AzureActivity
| where CategoryValue == "Policy"
| extend p = parse_json(Properties)
| extend policies = parse_json(tostring(p.policies))
| mv-expand policies
| where tostring(policies.policyDefinitionId) in~ (
"/providers/Microsoft.Authorization/policyDefinitions/4e6c27d5-a6ee-49cf-b2b4-d8fe90fa2b8b",
"/providers/Microsoft.Authorization/policyDefinitions/db4a9d17-db75-4f46-9fcb-9f9526604417")
| summarize Events = count(), LastSeen = max(TimeGenerated) by Caller, OperationNameValue
| sort by Events desc
797f4846-ba00-4fd7-ba43-dac1f8f63013), dus filter op die resource in zowel de interactieve als de niet-interactieve user sign-in-tabel: union SigninLogs, AADNonInteractiveUserSignInLogs
| where TimeGenerated > ago(30d)
| where ResourceIdentity == "797f4846-ba00-4fd7-ba43-dac1f8f63013"
| where ResultType == "0"
| where AuthenticationRequirement == "singleFactorAuthentication"
| summarize SignIns = count(), Clients = make_set(AppDisplayName),
Protocols = make_set(AuthenticationProtocol), IPs = make_set(IPAddress, 20),
LastSeen = max(TimeGenerated) by UserPrincipalName, UserType
| sort by SignIns desc
AuthenticationRequirement laat zien wat er voor die aanmelding vereist was, niet wat de gebruiker toevallig deed. In een tenant waar Conditional Access al MFA eist voor Azure-beheer blijven vooral je uitsluitingen over, en dat is precies de lijst die je zoekt. In een tenant zonder zo'n policy staat bijna alles op single factor, en dan zijn ropc in de protocolkolom (een script met een wachtwoord) en IP-adressen van build agents of automatiseringsservers de nuttige signalen. UserType geeft je de gasten er gratis bij. Automatisering naar workload identities verhuizen
Connect-AzAccount -Identity. Pipelines horen workload identity federation te gebruiken, zodat er helemaal geen secret bestaat: in GitHub Actions de azure/login-action met OpenID Connect en een federated credential op een app registration of user-assigned managed identity, in Azure DevOps een Azure Resource Manager service connection met workload identity federation (bestaande service connections met een secret die Azure DevOps zelf heeft aangemaakt, kun je ter plekke converteren). Voor code die ergens anders draait, bijvoorbeeld op een on-premises scheduler, is een service principal met een certificaat de terugvaloptie, liever geen client secret: Connect-AzAccount -ServicePrincipal -ApplicationId $appId -Tenant $tenantId -CertificateThumbprint $thumbprint
Kort samengevat: draai de sign-in-query over de afgelopen 30 dagen, leg elke UPN die eruit komt naast je lijst met Conditional Access-uitsluitingen, en geef elk account een eigenaar en een doelidentiteit (managed identity, federated credential of certificaat) voordat de volgende deployment draait die ervan afhangt.
Bronnen
- Verplichte MFA voor Azure en andere beheerportals (Learn)
- Azure blog: Azure mandatory multifactor authentication Phase 2 starting in October 2025
- MC1143999: uitstel van fase 2 van de verplichte MFA voor Azure
- Tutorial: MFA zelf afdwingen met Azure Policy
- Azure CLI troubleshooting: multifactor authentication
- Conditional Access: user exclusions in de MFA-policy voor alle gebruikers
- Emergency access accounts beheren
- Cross-tenant access settings voor B2B-collaboration
- Met GitHub Actions en OpenID Connect verbinden met Azure
- Azure Resource Manager service connection in Azure DevOps
- Conditional Access voor workload identities