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

Category:
FIM, Identity and Access Management, Office 365, PowerShell
Tags:
, , , ,

Join the conversation! 10 Comments

  1. […] post uses an almost identical Management Agent to the one described in this post. Review that post to get an understanding of the AzureAD Differential Queries. I’m not going […]

    Reply
  2. I’m Trying to use your Script with the current ADPreview Component
    ‘C:\Program Files\WindowsPowerShell\Modules\AzureADPreview\2.0.0.98

    When doing this, I get the following Error.
    New-Object : Cannot find an overload for “UserCredential” and the argument count: “2”.
    At C:\temp\GetUserObjectsFromAzure.ps1:45 char:10
    + $creds = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory. …

    Wich is referring to the following command…
    $creds = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.UserCredential” `
    -ArgumentList $Username,$Password

    What would I Need to change to get this running?

    Reply
    • Have you implemented it as a FIM/MIM Granfeldt Powershell Management Agent or are you just trying the powershell script as standalone ? If trying just as the script you will need to set values for $username and $password. When implemented as a PSMA these values are passed from the MA Config.

      Reply
      • Looks as if the UserCredential changed to UserPasswordCredential for 2.0.0.98 So I managed to work passed that Piece but now I get the error on the AcuireToken…
        >>
        Method invocation failed because [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext] does not contain a method named ‘AcquireToken’.

      • Just tested with the latest version of the library 2.0.0.98. Yes seeing the same thing as you. It works with earlier versions. Will look into it when I get a little time. Won’t be upgrading the modules where I’m using this library until I find a solution.

  3. Hi Darren
    I found the solution with a collegue at work. 🙂

    You Need to add 2 dll’s at the beginning

    # Adding the AD library to your PowerShell Session.
    Add-Type -Path ‘C:\Program Files\WindowsPowerShell\Modules\AzureADPreview\2.0.0.98\Microsoft.IdentityModel.Clients.ActiveDirectory.dll’
    Add-Type -Path ‘C:\Program Files\WindowsPowerShell\Modules\AzureADPreview\2.0.0.98\Microsoft.IdentityModel.Clients.ActiveDirectory.Platform.dll’

    and then use this to get $authenticationResult

    $creds = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.UserPasswordCredential” `
    -ArgumentList $username,$password

    # Create a authentication context with the above authentication string.
    $authContext = New-Object “Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContext” `
    -ArgumentList $authString

    # Acquire access token from server.
    $authenticationResult = [Microsoft.IdentityModel.Clients.ActiveDirectory.AuthenticationContextIntegratedAuthExtensions]::AcquireTokenAsync($authContext, $resource, $client_id, $creds).Result;

    This worked for me…

    Reply
  4. Is there a way to add additinal attribuets, e.g. extensionAttribute1-15, CountryCode or custom Attributes?

    Reply

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

%d bloggers like this: