How cool is the Azure Active Directory Graph?

I’ve been deploying Forefront Identity Manager (FIM) for the purpose of multi-forest synchronisation to Azure Active Directory (AAD), i.e. Office 365 directory synchronisation using FIM (again).  On one of my recent engagements we had some very tight timelines and as such FIM went in early.  Earlier than it should have.  So I had a lot of data errors to wade through.  We’d actually stood up FIM a year before, but for typical customer and sales-compete reasons, the project died and then was born again nearly a year later.  This meant that AAD was populated, but the synchronisation status was somewhat out of date – about seven weeks out of date (although the O365 project stalled for nine months the FIM instance I put in last year kept on chugging away without anyone watching it).

I uninstalled FIM and the original, unreleased O365 connector and installed a fresh FIM Synchronization Service installation with the AAD connector (at time of writing still in preview, but generally available to all via connect.microsoft.com).  I dropped my new, re-written configuration into the system and kicked-off the on-boarding exercise, i.e. import; sync, without provisioning.  I hit errors.  Lots and lots of errors, of course.

The reason I’m telling you this is because I utilised some cool tooling to help me fix these errors.  I won’t bore you with the all the issues but will focus on the bulk of them.  These related to the fact that there were a lot of contact, group and user objects in the tenant that either no longer existed or had been recreated (this is particularly painful as we have almost all attribute values the same but the unique identifier and anchor is different).  When exporting new objects I was getting lots of uniqueness conflicts – two different errors are thrown, one specifically calling out that the proxyAddresses value or values is not unique, ergo failed export; the other an invalid soft match (slightly bogus, and basically the same, i.e. duplicate proxyAddresses but this time on an unmanaged (orphaned) object).

So, I have to identify where the conflicts are and remedy.  The uniquness errors are on-premises duplicates; the invalid soft match errors are duplicates in the cloud – orphans.  This is the painful part.  I can’t see all of the proxyAddresses values via PowerShell!  Let me explain the issue and the resolution…

First things first.  Let’s get some users…

Connect-MsolService –Credential (Get-Credential svcfimaadma@tenant22.onmicrosoft.com)

(Get-MsolUser –SearchString paul).Count

OK, there’s only 12.  Let’s dump the proxyAddresses and see which one of those bad boys has the conflict…

Get-MsolUser –SearchString paul | % { “$($_.UserPrincipalName) <$($_.ProxyAddresses)>” }

If you’re wondering what that’s all about I’m intentionally wrapping the multivalued attribute proxyAddresses in quotes, basically dumping all values on one line as a String.  I do this inside of less than and greater than characters with the UPN before it.  It’s messy, but it’s painless and I can see what’s going on.

Hmmm…none of those objects have a conflicting proxyAddress.  In fact some of them don’t have any proxyAddresses.  That’s a little weird…

Is it?  No, it turns out.  When you read that value via PowerShell you’re only seeing a subset of the values!  You’re only seeing verified domains, e.g. paul.williams@verifiedtenant.com and paulw@verifiedtenant.onmicrosoft.com but not paul.williams@microsoft.com because I haven’t verified microsoft.com.  But the duplicate is the microsoft.com proxy!  Sad smile

And here is the reason for my rambling…The Azure AD Graph API.  There’s an example tool that allows you to submit queries against the Graph:

Now check this out…

Fire up the graph explorer.  Sign in.  Then try something like this in the resource box:

https://graph.windows.net/verifiedtenant.onmicrosoft.com/contacts?api-version=2013-04-05&$filter=proxyAddresses/any(c:startswith(c, ‘smtp:paul.williams’))

Hmmm, still no results.  Let’s check users…

https://graph.windows.net/verifiedtenant.onmicrosoft.com/users?api-version=2013-04-05&$filter=proxyAddresses/any(c:startswith(c, ‘smtp:paul.williams’))

Oh yeah.  There’s my conflict object!

{
  “odata.type”: “Microsoft.WindowsAzure.ActiveDirectory.User”,
  “objectType”: “User”,
  “objectId”: “8bcb67ba-2775-4eff-8088-6b320a4e7692”,
  “accountEnabled”: true,
  “assignedLicenses”: [],
  “assignedPlans”: [],
  “city”: null,
  “country”: “United Kingdom”,
  “department”: null,
  “dirSyncEnabled”: true,
  “displayName”: “Williams, Paul (Microsoft)”,
  “facsimileTelephoneNumber”: null,
  “givenName”: “Paul”,
  “jobTitle”: null,
  “lastDirSyncTime”: “2013-07-28T00:10:44Z”,
  “mail”: “Paul.Williams@microsoft.com”,
  “mailNickname”: “Paul.Williams1”,
  “mobile”: null,
  “otherMails”: [],
  “passwordPolicies”: null,
  “passwordProfile”: null,
  “physicalDeliveryOfficeName”: “Bryncoch”,
  “postalCode”: “SA10 2NB”,
  “preferredLanguage”: null,
  “provisionedPlans”: [],
  “provisioningErrors”: [],
  “proxyAddresses”: [
    “X500:/o=msresourceDotNet/ou=Central Administrative Admin Group/cn=Recipients/cn=Paul.Williams1”,
    “smtp:uugb422@verifiedtenant.net”,
    “smtp:Paul.Williams@verifiedtenant.onmicrosoft.com”,
    “SMTP:Paul.Williams@microsoft.com”
  ],
  “state”: “Wales”,
  “streetAddress”: “Some building\r\nSome Desirable Place\r\nSwansea\r\nSA1 2NB”,
  “surname”: “Williams”,
  “telephoneNumber”: null,
  “usageLocation”: null,
  “userPrincipalName”: uugb422@verifiedtenant.net
},

Look at the last DirSync time!  Let’s delete me…

Get-MsolContact –ObjectID 8bcb67ba-2775-4eff-8088-6b320a4e7692 | Remove-MsolContact –Force

This might be a silly example.  But I thought it was pretty cool and will try and find some time to invest in learning more about it.  Smile

Some more queries

Here’s some more queries that I’ve been using and that might be useful.  Most are available in the Azure graph documentation, but it’s nice and convenient to wrap up with some examples nonetheless.

User object with UPN equal to kkgb422@verifiedtenant.net

https://graph.windows.net/verifiedtenant.onmicrosoft.com/users?api-version=2013-04-05&$filter=userPrincipalName eq ‘kkgb422@verifiedtenant.net’

User objects with a proxyAddresses value that starts with SMTP:paul.williams

https://graph.windows.net/verifiedtenant.onmicrosoft.com/users?api-version=2013-04-05&$filter=proxyAddresses/any(c:startswith(c, ‘SMTP:paul.williams’))

Get an object’s manager (or other reference)

You can chase a reference using the GUID or the UPN to target the object.  Object GUID:

https://graph.windows.net/verifiedtenant.onmicrosoft.com/users/7a9400b5-6d98-4484-90dd-66b1d29fb542/$links/manager?api-version=2013-04-05

UPN:

https://graph.windows.net/verifiedtenant.onmicrosoft.com/users/kkgb422@verifiedtenant.net/$links/manager?api-version=2013-04-05

Note – $links returns the value (as an URL); omit $links to return the reference.

Advertisements

About Paul Williams

IT consultant working for Microsoft specialising in Identity Management and Directory Services.
This entry was posted in Azure, Azure Active Directory, Office 365 and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s