Microsoft Graph and the $whatIf option

What we know today as the Microsoft Graph has evolved over the last few years from a number of different API’s that were developed by different product teams within Microsoft (e.g Azure AD, Office 365, Outlook). That doesn’t mean the old ones have gone away, but it does mean that we can connect to the Microsoft Graph API and leverage the API’s we used to interface with independently.

What this means is, where information is actually coming from is obfuscated. But there is a way to find out where it is coming from.

The $whatIf option is a mostly undocumented switch that provides visibility on the source of information returned by Microsoft Graph from differing back-end API’s. The easiest way to use this is via the Graph Explorer.

Running a query using Graph Explorer for /me returns a bunch of information.

Graph me base request.PNG

Running the same query with the $whatIf option returns what the /me call actually performs on the API.

Graph me base request with whatIf.PNG

In this case it returns the base user information as shown below in the $select query.

{“Description”:”Execute HTTP request”,”Uri”:”https://graph.windows.net/v2/dcd219dd-bc68-4b9b-bf0b-4a33a796be35/users(’48d31887-5fad-4d73-a9f5-3c356e68a038′)?$select=businessPhones,displayName,givenName,jobTitle,mail,mobilePhone,officeLocation,preferredLanguage,surname,userPrincipalName,id“,”HttpMethod”:”GET”}

If I change the query to a specific user and request information that comes from different products behind the Microsoft Graph and I use the $whatIf option we can see where the data is coming from.

https://graph.microsoft.com/v1.0/users/MeganB@M365x214355.onmicrosoft.com?$select=mail,aboutMe&whatIf

The screenshot below shows that the request actually executed 2 requests in parallel and merge the entity responses

Data from multiple APIs.PNG

The result then shows where the two queries went. In this case graph.windows.net and sharepoint.com.

{“Description”:”Execute 2 request in parallel and merge the entity responses”,”Request1“:{“Description”:”Execute HTTP request”,”Uri”:”https://graph.windows.net/v2/dcd219dd-bc68-4b9b-bf0b-4a33a796be35/users(‘MeganB@M365x214355.onmicrosoft.com’)?$select=mail”,”HttpMethod”:”GET”},”Request2“:{“Description”:”Execute HTTP request”,”Uri”:”https://m365x214355.sharepoint.com/_api/SP.Directory.DirectorySession/GetSharePointDataForUser(’48d31887-5fad-4d73-a9f5-3c356e68a038′)?$select=aboutMe”,”HttpMethod”:”GET”}}

Summary

The next time you’re trying to workout where information is coming from when using the Microsoft Graph API, try adding the $whatIf switch to your query and have a look at the Response.

Azure Active Directory B2B Pending and Accepted User Reports

One of the benefits of Cloud Services is the continual enhancements that vendors provide based on feedback from their customers. One such item of feedback that Microsoft has heard often is the request to know what state a Guest user in Azure AD is in. In the last couple of days Microsoft exposed two additional attributes on the User objectClass in Azure AD;

  • externalUserState
  • externalUserStateChangeDateTime

B2B State Tweet.PNG

This means we can now query the Microsoft Graph for B2B users and understand if they have Accepted or are PendingAcceptance, and the datetime of the last change.

My customers have been wanting such information and would like to report on it. Here is an example PowerShell script I’ve put together that queries Microsoft Graph to locate B2B Users in the Accepted and PendingAcceptance states and outputs summary information into two HTML Reports. One for Accepted and one for PendingAcceptance.

Update the following script;

  • Line 2 for a Microsoft Azure PowerShell Module such as AzureAD that has the Microsoft.IdentityModel.Clients.ActiveDirectory.dll library in it
  • Line 5 for your Tenant name
  • Lines 15 and 16 for a Username and Password
  • Line 19 for where you want the Reports written to

Running the Script will then generate the Accepted and Pending HTML Reports.

Output Reports.PNG

Here is an example of the AcceptedB2BUsers HTML Report.

Accepted Report.png

Summary

With the addition of these two additional attributes to the Microsoft Graph we can now query for B2B users based on their State and using PowerShell quickly report on them.

How to create an AzureAD Microsoft Identity Manager Management Agent using the MS GraphAPI and Differential Queries

Introduction

In August 2016 I wrote this post on how to use PowerShell to leverage the Microsoft GraphAPI and use Differential Queries. The premise behind that post was I required a Microsoft Identity Manager Management Agent to synchronize identity information from AzureAD into Microsoft Identity Manager. However the environment it was intended for has a large AzureAD implementation and performing a Full Sync every-time is just to time consuming. Even more so with this limitation that still exists today in MIM 2016 with SP1.

In this blog post I’ll detail how to implement a PowerShell Management Agent for FIM/MIM to use the MS GraphAPI to synchronize objects into FIM/MIM, supporting Delta and Full Synchronization run profiles. I’m also using my favourite PowerShell Management Agent, the Granfeldt PowerShell Management Agent.

Pre-requsites

I’m using the ADAL helper library from the AzureADPreview PowerShell Module. Install that module on you MIM Sync Server via PowerShell (WMF5 or later) using the PowerShell command;

Install-Module AzureADPreview

Getting Started with the Granfeldt PowerShell Management Agent

If you don’t already have it, what are you waiting for. Go get it from here. Søren’s documentation is pretty good but does assume you have a working knowledge of FIM/MIM and this blog post is no different.

Three items I had to work out that I’ll save you the pain of are;

  • You must have a Password.ps1 file. Even though we’re not doing password management on this MA, the PS MA configuration requires a file for this field. The .ps1 doesn’t need to have any logic/script inside it. It just needs to be present
  • The credentials you give the MA to run this MA are the credentials for the account that has permissions to the AzureAD/Office365 Tenant. Just a normal account is enough to enumerate it, but you’ll need additional permissions if you intend to write-back to AzureAD.
  • The path to the scripts in the PS MA Config must not contain spaces and be in old-skool 8.3 format. I’ve chosen to store my scripts in an appropriately named subdirectory under the MIM Extensions directory. Tip: from a command shell use dir /x to get the 8.3 directory format name. Mine looks like C:\PROGRA~1\MICROS~4\2010\SYNCHR~1\EXTENS~2\AzureAD

Schema.ps1

My Schema is based around enumerating and managing users from AzureAD. You’ll need to create a number of corresponding attributes in the Metaverse Schema on the Person ObjectType to flow the attributes into. Use the Schema info below for a base set of attributes that will get you started. You can add more as required. I’ve prefixed most of them with AAD for my implementation.

If you want to manage Groups or Contacts or a combination of object types, you will need to update the Schema.ps1 script accordingly.

Import.ps1

The logic that the Import.ps1 implements is the same as detailed here in my post using Differential Queries. Essentially, perform a full import and create a file with the cookie/watermark. Allow Delta Sync run profiles to be performed by requesting the GraphAPI to return only changes since the cookie/watermark.

You’ll need to update the script for your AzureAD Tenant name on Line 28. Also the path to where the cookie file will go and the debug file if your path is different to mine. Lines 11, 46 and 47.

Importing of the attributes is based around the names in the Schema.ps1 scripts. Any changes you made there will need to be reflected in the import.ps1.

Password Script (password.ps1)

Empty as not implemented

Export.ps1

Empty as not implemented in this example. If you are going to write information back to AzureAD you’ll need to put the appropriate logic into this script.

Management Agent Configuration

With the Granfeldt PowerShell Management Agent installed on your FIM/MIM Synchronisation Server, in the Synchronisation Server Manager select Create Management Agent and choose “PowerShell” from the list of Management Agents to create.

As this example is for Users, I’ve named my MA accordingly.

As per the tips above, the format for the script paths must be without spaces etc. I’m using 8.3 format and I’m using an Office 365 account to connect to AzureAD/Office365 and import the user data.

Paths to the Import, Export and Password scripts. Note: the Export and Password PS1 scripts files exist but are empty.

Object Type as configured in the Schema.ps1 file.

Attributes as configured in the Schema.ps1 file.

Anchor as per the Schema.ps1 file.

The rest of the MA configuration is up to your implementation. What you are going to join on and what attributes flow into the MV will vary based on your needs and solution. At a minimum you’d probably be looking to do a join on immutableID (after some manipulation) or UPN and flow in attributes such as AADAccountEnabled etc.

Completing the Configuration

To finalise the MA you’ll need to do the usual tasks of creating run profiles, staging the connector space from AzureAD/Office365 and syncing into the Metaverse. Once you’ve done your initial Stage/Full Sync you can perform Delta Sync’s.

Summary

A “Full Import” on a small AzureAD (~8500 Users) took 2 minutes.
A subsequent “Delta Import” with no changes took 6 seconds.

A similar implementation of the logic, but for Groups gives similar results/performance.
A  “Full Import” on a small AzureAD (~9800 Groups) took 5 minutes.
A subsequent “Delta Import” with 7 Adds (new Groups) and 157 Updates took 1 minute.

 

Follow Darren on Twitter @darrenjrobinson