We’ve known for a while now that Microsoft plans to deprecate the good old MSOnline (and Azure AD) PowerShell modules in favor of the Microsoft Graph SDK for PowerShell, and the underlying Azure AD API endpoints in favor of the Graph API. As part of this, customers and ISVs have been trying to update their scripts and solutions, yet few distinct scenarios remain unaddressed and are in effect preventing the move to the Graph.
Until now, reporting on any errors in the provisioning (or deprovisioning) of Azure AD users was one such scenario. This was easily addressed via the MSOnline PowerShell cmdlets and specifically Get-MsolUser, which exposed the Errors property. Within said property, a nested XML ErrorDetail object provided the needed information to troubleshoot the corresponding issue. Here’s an example:
#List all users with provisioning errors $a = Get-MsolUser -HasErrorsOnly #List errors affecting a given user $a[0].Errors #Get the actual error message $a[0].Errors.ErrorDetail.ObjectErrors.ErrorRecord.ErrorDescription #text ----- {Exchange can't disable the mailbox "pta" because it is on In-Place Hold. ComplianceTagHoldApplied: false, DelayHoldApplied: false, DelayReleaseHoldApplied: false, OrganizationPolicies Applied: mb... {Exchange can't disable the mailbox "pta" because it is on In-Place Hold. ComplianceTagHoldApplied: false, DelayHoldApplied: false, DelayReleaseHoldApplied: false, OrganizationPolicies Applied: mb...
In a welcome update, Microsoft is now exposing the same data via the Graph API. Specifically, a new property has been introduced for the /users resource under the /beta endpoint, namely serviceProvisioningErrors. Here’s an example on how the output looks like:
GET https://graph.microsoft.com/beta/users?$select=id,userPrincipalName,serviceProvisioningErrors
As evident from the above screenshot, the whole XML is dumped within the property value, and the whole thing is not exactly easy to read. If fetching the output via PowerShell, we can of course make it a bit prettier. Here’s an example PowerShell snippet that fetches the set of users within our tenant along with any serviceProvisioningErrors values, then parses said values in a human-readable format.
$uri = 'https://graph.microsoft.com/beta/users?$select=id,userPrincipalName,serviceProvisioningErrors' $Gr = Invoke-WebRequest -Headers $AuthHeader1 -Uri $uri -Verbose -Debug $result = ($gr.Content | ConvertFrom-Json).value #Filter only the users with errors $Err = $result | ? {$_.serviceProvisioningErrors} #Human-readable output $Err | select userPrincipalName, @{n="Errors";e={ ([[xml]]$_.serviceProvisioningErrors.errorDetail).ServiceInstance.ObjectErrors.ErrorRecord.ErrorDescription } } userPrincipalName Errors ----------------- ------ ExRemoved-a6b3a47102d64cb5a2ecdeed31bdb512@michev.onmicrosoft.com Windows Live ID "ExRemoved-a6b3a47102d64cb5a2ecdeed31bdb512@michev.onmicrosoft.com" is reserved for the cloud-based service. Please use a different name. pta@michev.info {Exchange can't disable the mailbox "pta" because it is on In-Place Hold. ComplianceTagHoldApplied: false, DelayHoldApplied: false, DelayReleaseHoldApplied: false, OrganizationPolicies Applied: mbx6590cabc176344cba96d8fae0188764d:2, UserPolicies Applied: , restrictivePolicies ...
One thing you might have noticed in the above example is that we filtered out the results client-side. Naturally, the question as to whether we can filter on the serviceProvisioningErrors property server-side is possible, i.e. can we issue a Graph API query to only return users with provisioning errors? Unfortunately, the answer is no, but at this point you should be used to the limited filtering capabilities of the Graph. Still, it would be nice if Microsoft addressed this part of the equasion too, after all achieving this via the MSOnline module was as simple as:
Get-MsolUser -HasErrorsOnly
Hopefully as the newly introduced property matures to /v1.0 we will get support for server-side filtering! Documentation on the property is also missing at this point, so if you need to address additional scenarios, you’re on your own.
nice one! I found that not all the errors listed by the below CMDlet can be seen but you get a bit more info in from the graph bit it’s still not that helpful.
Microsoft.Online.Administration.ValidationError
Get-MsolUser -HasErrorsOnly | fl DisplayName,UserPrincipalName,@{Name=”Error”;Expression={($_.errors[0].ErrorDetail.objecterrors.errorrecord.ErrorDescription)}}
They split the Graph coverage between serviceProvisioningErrors and onPremisesProvisioningErrors… took a while to convince them something is missing 🙂
Are you seeing errors not covered by the above?