A Voice Assistant for Microsoft Identity Manager

This is the third and final post in my series around using your voice to query/search Microsoft Identity Manager or as I’m now calling it, the Voice Assistant for Microsoft Identity Manager.

The two previous posts in this series detail some of my steps and processes in developing and fleshing out this concept. The first post detailed the majority of the base functionality whilst the second post detailed the auditing and reporting aspects into Table Storage and Power BI.

My final architecture is depicted below.

Identity Manager integration with Cognitive Services and IoT Hub 4x3

I’ve put together more of an overview in a presentation format using GitPitch you can checkout here.

The why and how of the Voice Assistant for Microsoft Identity Manager

If you’re interested in building the solution checkout the Github Repo here which includes the Respeaker Python Script, Azure Function etc.

Let me know how you go @darrenjrobinson

Using your Voice to Search Microsoft Identity Manager – Part 2

Introduction

Last month I wrote this post that detailed using your voice to search/query Microsoft Identity Manager. That post demonstrated a working solution (GitHub repository coming next month) but was still incomplete if it was to be used in production within an Enterprise. I hinted then that there were additional enhancements I was looking to make. One is an Auditing/Reporting aspect and that is what I cover in this post.

Overview

The one element of the solution that has visibility of each search scenario is the IoT Device. As a potential future enhancement this could also be a Bot. For each request I wanted to log/audit;

  • Device the query was initiated from (it is possible to have many IoT devices; physical or bot leveraging this function)
  • The query
  • The response
  • Date and Time of the event
  • User the query targeted

To achieve this my solution is to;

  • On my IoT Device the query, target user and date/time is held during the query event
  • At the completion of the query the response along with the earlier information is sent to the IoT Hub using the IoT Hub REST API
  • The event is consumed from the IoT Hub by an Azure Event Hub
  • The message containing the information is processed by Stream Analytics and put into Azure Table Storage and Power BI.

Azure Table Storage provides the logging/auditing trail of what requests have been made and the responses.  Power BI provides the reporting aspect. These two services provide visibility into what requests have been made, against who, when etc. The graphic below shows this in the bottom portion of the image.

Auditing Reporting Searching MIM with Speech.png

Sending IoT Device Events to IoT Hub

I covered this piece in a previous post here in PowerShell. I converted it from PowerShell to Python to run on my device. In PowerShell though for initial end-to-end testing when developing the solution the body of the message being sent and sending it looks like this;

[string]$datetime = get-date
$datetime = $datetime.Replace("/","-")
$body = @{
 deviceId = $deviceID
 messageId = $datetime
 messageString = "$($deviceID)-to-Cloud-$($datetime)"
 MIMQuery = "Does the user Jerry Seinfeld have an Active Directory Account"
 MIMResponse = "Yes. Their LoginID is jerry.seinfeld"
 User = "Jerry Seinfeld"
}

$body = $body | ConvertTo-Json
Invoke-RestMethod -Uri $iotHubRestURI -Headers $Headers -Method Post -Body $body

Event Hub and IoT Hub Configuration

First I created an Event Hub. Then on my IoT Hub I added an Event Subscription and pointed it to my Event Hub.

IoTHub Event Hub.PNG

Streaming Analytics

I then created a Stream Analytics Job. I configured two Inputs. One each from my IoT Hub and from my Event Hub.

Stream Analytics Inputs.PNG

I then created two Outputs. One for Table Storage for which I used an existing Storage Group for my solution, and the other for Power BI using an existing Workspace but creating a new Dataset. For the Table storage I specified deviceId for Partition key and messageId for Row key.

Stream Analytics Outputs.PNG

Finally as I’m keeping all the data simple in what I’m sending, my query is basically copying from the Inputs to the Outputs. One is to get the events to Table Storage and the other to get it to Power BI. Therefore the query looks like this.

Stream Analytics Query.PNG

Events in Table Storage

After sending through some events I could see rows being added to Table Storage. When I added an additional column to the data the schema-less Table Storage obliged and dynamically added another column to the table.

Table Storage.PNG

A full record looks like this.

Full Record.PNG

Events in Power BI

Just like in Table Storage, in Power BI I could see the dataset and the table with the event data. I could create a report with some nice visuals just as you would with any other dataset. When I added an additional field to the event being sent from the IoT Device it magically showed up in the Power BI Dataset Table.

PowerBI.PNG

Summary

Using the Azure IoT Hub REST API I can easily send information from my IoT Device and then have it processed through Stream Analytics into Table Storage and Power BI. Instant auditing and reporting functionality.

Let me know what you think on twitter @darrenjrobinson

Using your Voice to Search Microsoft Identity Manager – Part 1

Introduction

Yes, you’ve read the title correctly. Speaking to Microsoft Identity Manager. The concept behind this was born off the back of some other work I was doing with Microsoft Cognitive Services. I figured it shouldn’t be that difficult if I just break down the concept into individual elements of functionality and put together a proof of concept to validate the idea. That’s what I did and this is the first post of the solution as an overview.

Here’s a quick demo.

Overview

The diagram below details the basis of the solution. There are a few extra elements I’m still working on that I’ll cover in a future post if there is any interest in this.

Searching MIM with Speech Overview

The solution works like this;

  1. You speak to a microphone connected to a single board computer with the query for Microsoft Identity Manager
  2. The spoken phrase is converted to text using Cognitive Speech to Text (Bing Speech API)
  3. The text phrase is;
    1. sent to Cognitive Services Language Understanding Intelligent Service (LUIS) to identify the target of the query (firstname lastname) and the query entity (e.g. Mailbox)
    2. Microsoft Identity Manager is queried via API Management and the Lithnet REST API for the MIM Service
  4. The result is returned to the single board computer as a text result phase which it then uses Cognitive Services Text to Speech to convert the response to audio
  5. The result is spoken back

Key Functional Elements

  • The microphone array I’m using is a ReSpeaker Core v1 with a ReSpeaker Mic Array
  • All credentials are stored in an Azure Key Vault
  • An Azure Function App (PowerShell) interfaces with the majority of the Cognitive Services being used
  • Azure API Management is used to front end the Lithnet MIM Webservice
  • The Lithnet REST API for the MIM Service provides easy integration with the MIM Service

Summary

Leveraging a lot of Serverless (PaaS) Services, a bunch of scripting (Python on the ReSpeaker and PowerShell in the Azure Function) and the Lithnet REST API it was pretty simple to integrate the ReSpeaker with Microsoft Identity Manager. An alternative to MIM could be any other service you have an API interface into. MIM is obviously a great choice as it can aggregate from many other applications/services.

Why a female voice? From a small response it was the popular majority.

Let me know what you think on twitter @darrenjrobinson

Implementing Azure API Management with the Lithnet Microsoft Identity Manager Rest API

Introduction

Earlier this week I wrote this post that detailed implementing the Lithnet REST API for FIM/MIM Service. I also detailed using PowerShell to interact with the API Endpoint.

Now lets imagine you are looking to have a number of Azure Serverless features leverage your Rest API enabled Microsoft Identity Manager environment. Or even offer it “as-a-Service”. You’ll want to have some visibility as to how it is performing, and you’ll probably want to implement features such as caching and rate limiting let alone putting more security controls around it. Enter Azure API Management, which provides all those functions and more.

In this post I detail getting started with Azure API Management by using it to front-end the Lithnet FIM/MIM Rest API.

Overview

In this post I will detail;

  • Enabling Azure API Management
  • Configuring the Lithnet FIM/MIM Rest API integration with Azure API Management
  • Accessing MIM via Azure API Management and the Lithnet FIM/MIM Rest API using PowerShell
  • Reporting

Prerequisites

For this particular scenario I’m interfacing Azure API Management with a Rest API that uses Digest Authentication. So even though it is a Windows WCF Webservice you could do something similar with a similar API Endpoint. If the backend API endpoint is using SSL it will need to have a valid certificate. Even though Azure API Management allows you to add your own certificates I had issues with Self Signed Certificates. I have it working fine with Lets Encrypt issued certificates. Obviously you’ll need an Azure Subscription as well as an App/Servive with an API.

Enabling Azure API Management

From the Azure Portal select Create a resource and search for API management and select it.

Add API Mgmt.PNG

Select Create

Create API Mgmt.PNG

Give your API Management Service a name, select a subscription, resource group etc and select Create.

API Mgmt Config 1.PNG

Once you select Create it will take about 30 minutes to be deployed.

Configuring the Lithnet FIM/MIM Rest API integration with Azure API Management

Once your new API Management service has been deployed, from the Azure Portal select the API Management services blade and select the API Management service that you just created. Select APIs.

API Config 1.PNG

Select Add API and then select Add a new API

API Mgmt Config 2.PNG

Give the API a name, description, enter the URI for your API EndPoint, and select HTTPS. I’m going to call this MIMSearcher so have entered that under API URL Suffix. For initial testing under Products select starter. Finally select Create.

API Mgmt Config 4.PNG

We now have our base API setup. From the Backend tile select the Edit icon.

API Mgmt Config 5.PNG

As the backed is authenticated using Basic Authentication, select Basic in Gateway credentials and enter the details of an account with access that will be used by the API Gateway. Select Save.

API Mgmt Config 6.PNG

Now from our API Configuration select Add operation.

API Mgmt Config 7.PNG

First we will create a test operation for the Help page on the Lithnet FIM/MIM Rest API. Provide a Display name, and for the URL add /v2/help. Give it a description and select Create.

Note: I could have had v2 as part of the base URI for the API in the previous steps. I didn’t as I will be using API’s from both v1 and v2 and didn’t want to create multiple operations.

API Mgmt Config 8.PNG

Select the new Operation (Help)

API Mgmt Config 9.PNG

Select the Test menu. Select Send.

API Mgmt Config 10.PNG

If everything is set up correctly you will get a 200 Success OK response as below.

API Mgmt Config 11.PNG

Accessing MIM via Azure API Management and the Lithnet FIM/MIM Rest API using PowerShell

Head over to your API Portal. The URL is https://.portal.azure-api.net/ where is the name you gave your API Management Service shown in the third screenshot at the top of this post. If you are doing this from the browser you used to create the API Management Service you should be signed in already. From the Administrator menu on the right select Profile.

Test API Mgmt 1.PNG

Click on Show under one of the keys and record its value.

Test API Mgmt 2.PNG

Using PowerShell ISE or VSCode update the following Code Snippet and test.

$APIURL = 'https://.azure-api.net//v2/help'
$secret = 'yourSecret'
$Headers = @{'Ocp-Apim-Subscription-Key' = $secret} 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$response = Invoke-RestMethod -Uri $APIURL -Headers $Headers -ContentType "application/json" -UseBasicParsing -Method Get
$response

The snippet will create a Web Request to the new API and display the results.

Test API Mgmt 3.PNG

Querying the Lithnet Rest API via Azure API Management

Now that we have a working solution end-to-end, let’s do something useful with it. Looking at the Lithnet Rest API, the Resources URI is the key one exposing Resources from the MIM Service.

Resources.PNG

Let’s create a new Operation for Resources similar to what we did for the Help. After selecting Create configure the Backend for Basic Authentication like we did for Help.

Get Resources.PNG

Testing out the newly exposed endpoint is very similar to before. Just a new APIURL with the addition of /?Person to return all Person Resources from the MIM Portal. It lets us know it’s returned 7256 Person Objects, and the Results are still paged (100 by default).

Get Persons.PNG

Let’s now Search for just a single user. Search for a Person object whose Display Name is ‘darrenjrobinson’.

$query = "Person[DisplayName='darrenjrobinson']"
$queryEncoded = [System.Web.HttpUtility]::UrlEncode($query)

$APIURL = "https://.azure-api.net//v2/resources/?filter=/$($queryEncoded)" 
$secret = 'yourSecret'
$Headers = @{'Ocp-Apim-Subscription-Key' = $secret} 
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

$user = Invoke-RestMethod -Uri $APIURL -Headers $Headers -ContentType "application/json" -UseBasicParsing -Method Get
$user

Executing, we get a single user returned.

Search for User.PNG

Reporting

Using the Publisher Portal we can get some Stats on what is happening with our API Management implementation.

Go to https://.portal.azure-api.net/admin and select Analytics.

We then have visibility to what has been using the API Management Service. At a Glance gives and overview and you can drill down into;

  • Top Users
  • Top Products
  • Top subscriptions
  • Top APIs
  • Top Operations

At a glance looks like this;

At a Glance Stats.PNG

And Top Operations looks like this;

Top Operations.PNG

Summary

That is a quick start guide to implementing Azure API Management in front of a Rest API and using PowerShell to integrate with it. Next steps would be to enable caching, and getting into more of the advanced features. Enjoy.

 

Getting started with the Lithnet REST API for the Microsoft Identity Manager Service

Introduction

A common theme with my posts on Microsoft Identity is the extensibility of it particularly with the Lithnet tools that Ryan has released.

One such tool that I’ve used but never written about is the Lithnet REST API for the Microsoft Identity Manger Service. For a small proof of concept I’m working on I was again using this REST API and I needed to update it as Ryan has recently added some new functionality. I realised I hadn’t set it up in a while and while Ryan’s documentation is very good it was written some time ago when IIS Manager looked a little different. So here is a couple of screenshots and a little extra info to get you started if you haven’t used it before to supplement Ryan’s documentation located here.

Configuring the Lithnet REST API for the Microsoft Identity Manager Service

You can download the Lithnet REST API for the FIM/MIM Service from here

If you are using the latest version of the Lithnet Rest API you will need to make sure you have .NET 4.6.1 installed. If you are running Windows Server 2012 R2 you can get it from here.

When configuring your WebSite make sure you choose .NET v4.5 Classic for the Application Pool.

WebSite AppPool Settings.PNG

The web.config must match your MIM version. Currently the latest is 4.4.1749.0 as detailed here. That therefore looks like this.

WebConfig Resource Management Version.PNG

Finally you’ll need an SSL Certificate. For development environments a Self-Signed Certificate is fine. Personally I use this Cert Generator. Make sure you put the certificate in the cert store on the machine you will be testing access with. Here’s an example of my command line for generating a cert.

Cert Generation.PNG

You could also use Lets Encrypt.

In your bindings in IIS have the Host Name match your certificate.

Bindings.PNG

If you’ve done everything right you will be able to hit the v2 endpoint help. By default with Basic Auth enabled you’ll be prompted for a username and password.

v2 EndPoint.PNG

Using PowerShell to query MIM via the Lithnet Rest API

Here is an example script to query MIM via the Lithnet MIM Rest API. Update for your credentials (Lines 2 and 3), the URL of the server running the API Endpoint (Line 11) and what you are querying for (Line 14). My script takes into account Self Signed Certs in a Development environment.

Example output from a query is shown below.

Example Output.PNG

Summary

Hopefully that helps you quickly get started with the Lithnet REST API for the FIM/MIM Service. I showed an example using PowerShell directly, but using an Azure Function is also a valid pattern. I’ve covered similar functionality in the past.

 

How to use the FIM/MIM Azure Graph Management Agent for B2B Member/Guest Sync between Azure Tenants

Introduction

UPDATE: June 2018
When I originally wrote this post the intent was to test
the ability of the Graph MA to export to Azure AD. 
That works.

That then extended to messing with an identity type other 
than member (which works to an extent) but I detailed 
guests. However that is incomplete. I do have a working 
solution that utilises the Graph Invitation API via my 
favourite PowerShell MA (Granfeldt PS MA) and the 
PowerShell cmdlet New-AzureADMSInvitation from the 
Azure AD PowerShell Module.

That solution involves the MS Graph MA connected to a 
Partner tenant to get visibility of partner users and 
then creating relevant users in the home tenant via a 
PowerShell MA and the New-AzureADMSInvitation cmdlet. 
Another MS Graph MA connected to the home tenant provides 
easy visibility of additional guest user attributes for
ongoing functions such as reporting and de-provisioning. 

I will write that up later in July.  Stay tuned and keep
the above in mind when reading this post.

Just landed from the Microsoft Identity Manager Engineering Team is a new Management Agent built specifically for managing Azure Users and Groups and Contacts.

Microsoft have documented a number of scenarios for implementing the management agent. The scenarios the MA has been built for are valid and I have customers that will benefit from the new MA immediately. There is however another scenario I’m seeing from a number of customers that is possible but not detailed in the release notes. That is B2B Sync between Azure Tenants; using Microsoft Identity Manager to automate the creation of Guests in an Azure Tenant.

This could be one-way or two-way depending on what you are looking to achieve. Essentially this is the Azure equivalent of using FIM/MIM for Global Address List Sync.

B2B MA.png

Overview

The changes are minimal to the documentation provided with the Management Agent. Essentially;

  • ensure you enable Write Permissions to the Application you create in the AAD Tenant you will be writing too
  • Enable Invite Guest to the Organization permission on the AAD Application
  • Create an Outbound Sync Rule to an AAD Tenant with the necessary mandatory attributes
  • Configure the Management Agent for Export Sync Profiles

In the scenario I’m detailing here I’m showing taking a number of users from Org2 and provisioning them as Guests in Org1.

What I’m detailing here supplements the Microsoft documentation. For configuring the base MA definitely checkout their documentation here.

Microsoft Graph Permissions

When setting up the Graph Permissions you will need to have Write permissions to the Target Azure AD for at least Users. If you plan to also synchronize Groups or Contacts you’ll need to have Write permissions for those too.

Graph Permissions 1

In addition as we will be automating the invitation of users from one Tenant to another we will need to have the permission ‘Invite guest users to the organization’.

Graph Permissions 2

With those permissions selected and while authenticated as an Administrator select the Grant Permissions button to assign those permissions to the Application.

Grant Permissions 1Grant Permissions 2

Repeat this in both Azure AD Tenants if you are going to do bi-directional sync.  If not you only need write and invite permissions on the Tenant you will be creating Guest accounts in.

Creating the Import/Inbound Sync Rules Azure Tenants

Here is an example of my Import Sync Rules to get Members (Users) in from an Azure Tenant. I have an inbound sync rule for both Azure Tenants.

Sync Rules.PNG

Make sure you have ‘Create Resource in FIM‘ configured on the source (or both if doing bi-directional) Graph Connector.

Sync Rule Relationship.PNG

The attribute flow rules I’ve used are below. They are a combination of the necessary attributes to create the corresponding Guest account on the associated management agent and enough to be used as logic for scoping who gets created as a Guest in the other Tenant. I’ve also used existing attributes negating the need to create any new ones.

Inbound SyncRule Flow.PNG

Creating the Export/Outbound Sync Rule to a Partner B2B Tenant

For your Export/Outbound rule make sure you have ‘Create resource in external system’ configured.

Export Relationship.PNG

There are a number of mandatory attributes that need to be flowed out in order to create Guests in Azure AD. The key attributes are;

  • userType = Guest
  • accountEnabled = True
  • displayName is required
  • password is required (and not export_password as normally required on AD style MA’s in FIM/MIM)
  • mailNickname is required
  • for dn and id initially I’m using the id (flowed in import to employeeID) from the source tenant. This needs to be provided to the MA to get the object created. Azure will generate new values on export so we’ll see a rename come back in on the confirming import
  • userPrincipalName is in the format of
    • SOURCEUPN (with @ replaced with _ ) #EXT# DestinationUPNSuffix
    • e.g user1_org2.com#EXT#org1.com

Export Attributes.PNG

Here is an example of building a UPN.

UPN Rule.PNG

Sets, Workflows and MPR’s

I didn’t need to do anything special here. I just created a Set based on attributes coming in from the source Azure Tenant to scope who gets created in the target Tenant. An MPR that looks for transition into the Set and applies the Workflow that associates the Sync Rule.

End to End

After synchronizing in from the source (B2B Org 2) the provisioning rules trigger and created the Users as Guests on B2B Org 1.

Prov to Org1 1.PNG

Looking at the Pending Export we can see our rules have applied.

Pending Export.PNG

On Export the Guest accounts are successfully created.

Export Success.PNG

On the confirming import we get the rename as Azure has generated a new CN and therefore DN for the Guest user.

Rename on Import 2.PNG

Looking into Azure AD we can see one of our new Guest users.

User in AAD.PNG

Summary

Using the Microsoft Azure B2B Graph Management Agent we can leverage it to create users from one Tenant as Azure AD Members in another Tenant. Stay tuned for another post detailed the solution detailed in the Update in the Introduction.

Using Microsoft Identity Manager Synchronisation Server’s Global Address List Synchronisation feature to create a shared global address book across three Exchange Forests

First published at https://nivleshc.wordpress.com

Introduction

Over the life of a company, there can be many acquisitions and mergers. During such events, the parent and the newly acquired entities have their IT “merged”. This allows for the removal of redundant systems and the reduction of expenses. It also fosters collaboration between the two entities. Unfortunately, the marriage of the two IT systems, can at times, take a long time.

To enable a more collaborative space between the parent and the newly acquired company, a shared “global address book” can be created, which will allow employees to quickly look up each others contact details easily.

In this blog, I will show how we can use Microsoft Identity Manager (MIM) 2016 Synchronisation Server’s  GALSync feature to extend the Global Address Book (GAL) of three Exchange Forests. The GAL will be populated with contacts corresponding to  mailboxes in the other Exchange Forests, and this will be automatically maintained, to ensure the contacts remain up-to-date.

Though this blog focuses on three Exchange Forests, it can easily be adapted for two Exchange Forests, if you remove all reference to the third AD Forest, AD Domain and Exchange Forest

For reference, we will be using the following:

Name: Contoso Limited (parent company)
Active Directory Forest: contoso.com
Active Directory Domain: contoso.com
Active Directory Forest Level: Windows Server 2008 R2
Exchange Server FQDN: CEX01.contoso.com
Exchange Server Version: Exchange 2010 SP3
Email Address Space owned: contoso.com, contoso.com.au
Number of employees: 2000

Name: Northwind Traders (newly acquired)
Active Directory Forest: northwind.com
Active Directory Domain: northwind.com
Active Directory Forest Level: Windows Server 2008 R2
Exchange Server FQDN: NWEX01.northwind.com
Exchange Server Version: Exchange 2010 SP3
Email Address Space owned: northwind.com, northwind.com.au
Number of employees: 400

Name: WingTip Toys (newly acquired)
Active Directory Forest: wingtiptoys.com
Active Directory Domain: wingtiptoys.com
Active Directory Forest Level: Windows Server 2008 R2
Exchange Server FQDN: WTTEX01.wingtiptoys.com
Exchange Server Version: Exchange 2010 SP3
Email Address Space owned: wingtiptoys.com, wingtiptoys.com.au
Number of employees: 600

 

Contoso, Northwind and WingTip Toys are connected using a wide area network and it has been decided that the MIM Synchronisation Server will be installed and configured in the the Contoso domain.

Preparation

Before we start, some preparation work has to be done to ensure there are no roadblocks or issues.

  • Cleanup of “inter forest” email objects
    • This is one of the most important things that must be done and I can’t stress this enough. You will have to go through all your email objects (mailboxes, contacts, mailuser objects) in each of the three Exchange Forests (Contoso, Northwind, WingTip Toys) and find any that are forwarding to the other Exchange forests. If there are any, these must be removed. GALSync will create email enabled contacts corresponding to the mailboxes in the other Exchange Forests, with  externalemailaddress of these new objects set to the primary email address of the other Exchange Forest’s objects. If duplicates arise because there were existing objects in the local Exchange Forest corresponding to the other Exchange Forest’s objects, this will cause the local Exchange Server to get confused and it will keep on queuing emails for these objects and will not deliver them [if after implementing GALSync, some users complain about not receiving emails from a certain Exchange Forest, this could be a possible reason]
  • Creation of Organisational Units (OU) that will be used by GALSync
    • Create the following Organisational Units in the three Active Directory domains
      • contoso.com\GALSync\LocalForest\Contacts
      • contoso.com\GALSync\RemoteForest\Contacts
      • northwind.com\GALSync\LocalForest\Contacts
      • northwind.com\GALSync\RemoteForest\Contacts
      • wingtiptoys.com\GALSync\LocalForest\Contacts
      • wingtiptoys.com\GALSync\RemoteForest\Contacts
  • Service Accounts
    • The following service accounts must be created in the specified Active Directory domains. You can change the name to comply with your own naming standards
      • MIM Synchronisation Server Service Account
        • UPN: svc-mimsync@contoso.com
        • AD Domain to create in: contoso.com
        • Permissions: non-privileged Active Directory service account
      • Management Agent Account to connect to Contoso.com AD Domain
        • UPN: svc-mimadma@contoso.com
        • AD Domain to create in: contoso.com
        • Permissions
          • non-privilged Active Directory service account
          • Grant “Replicating Directory Changes” permission
          • Grant the following permissions on the GALSync OU in the Contoso AD Domain that was created above. Ensure the permissions propagate to all sub-OUs within the GALSync OU
            • Create Contact Objects
            • Delete Contact Objects
            • Read all Properties
            • Write all Properties
          • Add to the Exchange Organization Management Active Directory security group in Contoso AD Domain
      • Management Agent Account to connect to Northwind.com AD Domain
        • UPN: svc-mimadma@northwind.com
        • AD Domain to create in: nothwind.com
        • Permissions
          • non-privilged Active Directory service account
          • Grant “Replicating Directory Changes” permission
          • Grant the following permissions on the GALSync OU in the Northwind AD Domain that was created above. Ensure the permissions propagate to all sub-OUs within GALSync OU
            • Create Contact Objects
            • Delete Contact Objects
            • Read all Properties
            • Write all Properties
          • Add to the Exchange Organization Management Active Directory security group in Northwind AD Domain
      • Management Agent Account to connect to WingTiptoys.com AD Domain
        • UPN: svc-mimadma@wingtiptoys.com
        • AD Domain to create in: wingtiptoys.com
        • Permissions
          • non-privilged Active Directory service account
          • Grant “Replicating Directory Changes” permission
          • Grant the following permissions on the GALSync OU in the WingTipToys AD Domain that was created above. Ensure the permissions propagate to all sub-OUs within GALSync OU
            • Create Contact Objects
            • Delete Contact Objects
            • Read all Properties
            • Write all Properties
          • Add to the Exchange Organization Management Active Directory security group in Northwind AD Domain
      • Service account used for the scheduled task job that will run the MIM RunProfiles script on the MIM Synchronisation Server
        • UPN: svc-mimscheduler@contoso.com
        • AD Domain to create in: Contoso.com (this can also be a local account on the MIM Synchronisation Server)
        • Permissions
          • non-privileged Active Directory service account
          • Grant “Log on as a batch job” user right on the MIM Synchronisation Server
          • Add to FIMSyncOperators security group on the MIM Synchronisation Server (this security group is created locally on the MIM Synchronisation Server after MIM Synchronisation Server has been installed)
  • SQL Server Permissions
    • MIM Synchronisation Server requires a Microsoft SQL Server to host its database. On the SQL Server, grant SQL SYSADMIN role to the account that you will be logged on as when installing MIM Synchronisation Server

Configuration

Provision a Microsoft Windows Server 2012 R2 in the Contoso.com Active Directory domain and install MIM 2016 Synchronisation Server. During installation, specify svc-mimsync@contoso.com as the account under which the MIM Synchronisation Service will run.

One thing to note is that GALSync will update the proxyaddress field for all mailboxes in its scope (mailboxes for which it will be creating contacts in the other Exchange Forests) with X500 entries.

Management Agent Configuration

  1. Once the MIM Synchronisation Server has been successfully installed, use the following steps to create the GALSync Management Agents. Open the Synchronisation Service Manager
    • Create GALSync Management Agent for Contoso.com AD Forest
      • From Tools menu, click Management Agents and then click Create
      •  In the Management Agent drop-down list, click Active Directory global address list (GAL) 
      • In the name type GALSyncMA for Contoso.com
      • On the Connect to an Active Directory Forest page, type the forest name, the MIM MA account details (svc-mimadma@contoso.com) and the domain name
      • In the next screen, specify the OUs that GALSync will query to find mailboxes to create contacts for in the other forests. Also, place a tick beside contoso.com\GALSync (this selects GALSync and all sub-OUs)
      • In the Containers screen, for
        • Target Container select Contoso.com\GALSync\RemoteForest\Contactsthis is the OU where MIM GALSync will create contacts corresponding to the mailboxes in Northwind and WingTipToys Exchange Forest
        • Source Container select Contoso.com\GALSync\LocalForest\Contactsthis is where MIM GALSync will create contacts corresponding to Contoso.com mailboxes. These will be sent to the GALSync/RemoteForest/Contacts OU in Northwind and WingTipToys AD Domain (personally, I haven’t seen any objects created in this OU)
      • In Exchange Configuration click Edit and enter all the email suffixes that belong to Contoso.com. The email suffixes listed here are used to filter out which email addresses from the original email object are added to the corresponding contact in the other Exchange Forests. In this case the email suffixes will be @contoso.com and @contoso.com.au. Note the @ before the email suffix)
      • Leave everything else as default and proceed to the Configure Extensions section. One thing I would like to mention here is that in Configure Connection Filter section, the Filter Type for user is supposed to be Declared (and is the default setting), not Rules extension as stated in https://technet.microsoft.com/en-us/library/cc708642(v=ws.10).aspx
      • In the Configure Extensions section, set the following
      • Click OK
    • Create GALSync Management Agent for Northwind.com AD Forest
      • From Tools menu, click Management Agents and then click Create
      •  In the Management Agent drop-down list, click Active Directory global address list (GAL) 
      • In the name type GALSyncMA for Northwind.com
      • On the Connect to an Active Directory Forest page, type the forest name, the MIM MA account details (svc-mimadma@northwind.com) and the domain name
      • In the next screen, specify the OUs that GALSync will query to find mailboxes to create contacts for in the other forests. Also, place a tick beside northwind.com\GALSync (this selects GALSync and all sub-OUs)
      • In the Containers screen, for
        • Target Container select Northwind.com\GALSync\RemoteForest\Contactsthis is the OU where MIM GALSync will create contacts corresponding to the mailboxes in Contoso and WingTipToys Exchange Forest
        • Source Container select Northwind.com\GALSync\LocalForest\Contactsthis is where MIM GALSync will create contacts corresponding to Northwind.com mailboxes. These will be sent to the GALSync/RemoteForest/Contacts OU in Contoso and WingTipToys AD Domain (personally, I haven’t seen any objects created in this OU)
      • In Exchange Configuration click Edit and enter all the email suffixes that belong to Northwind.com. The email suffixes listed here are used to filter out which email addresses from the original email object are added to the corresponding contact in the other Exchange Forests. In this case the email suffixes will be @northwind.com and @northwind.com.au. Note the @ before the email suffix)
      • Leave everything else as default and proceed to the Configure Extensions section. One thing I would like to mention here is that in Configure Connection Filter section, the Filter Type for user is supposed to be Declared (and is the default setting), not Rules extension as stated in https://technet.microsoft.com/en-us/library/cc708642(v=ws.10).aspx
      • In the Configure Extensions section, set the following
      • Click OK
    • Create GALSync Management Agent for WingTipToys.com AD Forest
      • From Tools menu, click Management Agents and then click Create
      •  In the Management Agent drop-down list, click Active Directory global address list (GAL) 
      • In the name type GALSyncMA for WingTipToys.com
      • On the Connect to an Active Directory Forest page, type the forest name, the MIM MA account details (svc-mimadma@wingtiptoys.com) and the domain name
      • In the next screen, specify the OUs that GALSync will query to find mailboxes to create contacts for in the other forests. Also, place a tick beside wingtiptoys.com\GALSync (this selects GALSync and all sub-OUs)
      • In the Containers screen, for
        • Target Container select WingTipToys.com\GALSync\RemoteForest\Contactsthis is the OU where MIM GALSync will create contacts corresponding to the mailboxes in Contoso and Northwind Exchange Forest
        • Source Container select WIngTipToys.com\GALSync\LocalForest\Contactsthis is where MIM GALSync will create contacts corresponding to WingTipToys.com mailboxes. These will be sent to the GALSync/RemoteForest/Contacts OU in Contoso and Northwind AD Domain (personally, I haven’t seen any objects created in this OU)
      • In Exchange Configuration click Edit and enter all the email suffixes that belong to WingTipToys.com. The email suffixes listed here are used to filter out which email addresses from the original email object are added to the corresponding contact in the other Exchange Forests. In this case the email suffixes will be @wingtiptoys.com and @wingtiptoys.com.au. Note the @ before the email suffix)
      • Leave everything else as default and proceed to the Configure Extensions section. One thing I would like to mention here is that in Configure Connection Filter section, the Filter Type for user is supposed to be Declared (and is the default setting), not Rules extension as stated in https://technet.microsoft.com/en-us/library/cc708642(v=ws.10).aspx
      • In the Configure Extensions section, set the following
      • Click OK
  2. Enable provisioning by using the following steps
    • In the Synchronisation Service Manager, from Tools select Options
    • Under Metaverse Rules Extensions ensure the following have been ticked
      • Enable metaverse rules extensions
      • Enable Provisioning Rules Extension

Run Profiles Execution Order

Congratulations! All configuration has now been completed. All we have to do now is to run the synchronisation jobs to get the mailbox object information from the three AD Forests into the MIM metaverse, let MIM GALSync do a bit of processing to find out which contacts are to be created in the other Exchange Forests, and then carry out an export, to create those contacts in the other Exchange Forests. Unfortunately, MIM has no way of finding out if the exports were successful, and that is why we will have to do a confirming import on all the management agents, so that MIM can find out if everything had been exported as expected.

From my testing, I have found that when MIM GALSync does its processing, it compares the mailboxes that an Exchange Forest has with what is in the MIM metaverse. MIM then exports out, as contacts, all objects that are in the metaverse but not in that particular Exchange Forest. These are populated in that AD Domains GALSync/RemoteForest/Contacts OU as AD objects and subsequently mail enabled using the Exchange RPS URI (remote PowerShell url)

CAUTION! Before you continue, you need to find out if a synchronisation solution had previously been deployed in the environment.

If any of the AD Forests had previously had a synchronisation solution deployed, then we will need to follow the run profile execution order mentioned below. This is done to ensure no duplicate contacts are created during the initial GAL synchronisation.

  1. Full Import (Staging Only) on GALSyncMA for Contoso.com
  2. Full Import (Staging Only) on GALSyncMA for Northwind.com
  3. Full Import (Staging Only) on GALSyncMA for WingTipToys.com
  4. Delta Synchronisation on GALSyncMA for Contoso.com
  5. Delta Synchronisation on GALSyncMA for Northwind.com
  6. Delta Synchronisation on GALSyncMA for WingTipToys.com
  7. Repeat Delta Synchronisation on GALSyncMA for Contoso.com
  8. Repeat Delta Synchronisation on GALSyncMA for Northwind.com
  9. Repeat Delta Synchronisation on GALSyncMA for WingTipToys.com
  10. Export on GALSyncMA for Contoso.com
  11. Export on GALSyncMA for Northwind.com
  12. Export on GALSyncMA for WingTipToys.com
  13. Delta Import on GALSyncMA for Contoso.com
  14. Delta Import on GALSyncMA for Northwind.com
  15. Delta Import on GALSyncMA for WingTipToys.com

 

If there hasn’t been any previous synchronisation solutions deployed in any of the AD Forests, then use the following runprofile order for the initial run

  1. Full Import (Staging Only) on GALSyncMA for Contoso.com
  2. Full Import (Staging Only) on GALSyncMA for Northwind.com
  3. Full Import (Staging Only) on GALSyncMA for WingTipToys.com
  4. Full Synchronisation on GALSyncMA for Contoso.com
  5. Full Synchronisation on GALSyncMA for Northwind.com
  6. Full Synchronisation on GALSyncMA for WingTipToys.com
  7. Export on GALSyncMA for Contoso.com
  8. Export on GALSyncMA for Northwind.com
  9. Export on GALSyncMA for WingTipToys.com
  10. Delta Import on GALSyncMA for Contoso.com
  11. Delta Import on GALSyncMA for Northwind.com
  12. Delta Import on GALSyncMA for WingTipToys.com

 

Once the initial synchronisation has completed, you will see contacts in each AD Domain’s GALSync\RemoteForest\Contacts OU corresponding to mailboxes in the other two Exchange Forests. These will have been email enabled and will show in the Exchange console and the online Global Address List.

Outlook clients that use offline address books won’t see the new contacts until the offline address book generation process has run on the Exchange servers and the updated offline address book has been downloaded by the outlook client.

To ensure the GALSync generated contacts remain up-to-date, the following runprofile execution order must be used from hereon. This should be repeated every 1 hour (or as per your required interval. Keep in mind that if after one cycle of the following order, if anything is still pending an Export, then this will be run at the next runprofile execution, so changes might not be seen for at most two runcycle intervals)

  1. Delta Import (Staging Only) on GALSyncMA for Contoso.com
  2. Delta Import (Staging Only) on GALSyncMA for Northwind.com
  3. Delta Import (Staging Only) on GALSyncMA for WingTipToys.com
  4. Delta Synchronisation on GALSyncMA for Contoso.com
  5. Delta Synchronisation on GALSyncMA for Northwind.com
  6. Delta Synchronisation on GALSyncMA for WingTipToys.com
  7. Export on GALSyncMA for Contoso.com
  8. Export on GALSyncMA for Northwind.com
  9. Export on GALSyncMA for WingTipToys.com
  10. Delta Import on GALSyncMA for Contoso.com
  11. Delta Import on GALSyncMA for Northwind.com
  12. Delta Import on GALSyncMA for WingTipToys.com

I don’t imagine anyone would want to run the runprofiles manually every hour 😉 So below is a script that can be used to do it.

Export all the runprofiles using the Synchronisation Service Manager as vbs scripts and place them in a folder c:\scripts\runprofiles on the MIM Synchronisation Server.

Copy the below script and save it as GALSync_RunProfiles.cmd in c:\scripts

@echo off
REM This script will run the MIM RunProfiles in the correct order
REM Author nivleshc@yahoo.com

set _script_dir="c:\scripts\runprofiles\"

REM Delta Import (Stage Only)
echo ContosoGALSyncMA Delta Import -StageOnly
CSCRIPT //B %_script_dir%ContosoGALSyncMA_Delta_Import_StageOnly.vbs

echo NorthwindGALSyncMA Delta Import -StageOnly
CSCRIPT //B %_script_dir%NorthwindGALSyncMA_Delta_Import_StageOnly.vbs

echo WingTipToysGAlSyncMA Delta Import -StageOnly
CSCRIPT //B %_script_dir%WingTipToysGAlSyncMA_Delta_Import_StageOnly.vbs

REM Delta Sync
echo ContosoGALSyncMA Delta Sync
CSCRIPT //B %_script_dir%ContosoGALSyncMA_Delta_Sync.vbs

echo NorthwindGALSyncMA Delta Sync
CSCRIPT //B %_script_dir%NorthwindGALSyncMA_Delta_Sync.vbs

echo WingTipToysGAlSyncMA Delta Sync
CSCRIPT //B %_script_dir%WingTipToysGAlSyncMA_Delta_Sync.vbs

REM Export
echo ContosoGALSyncMA Export
CSCRIPT //B %_script_dir%ContosoGALSyncMA_Export.vbs

echo NorthwindGALSyncMA Export
CSCRIPT //B %_script_dir%NorthwindGALSyncMA_Export.vbs

echo WingTipToysGAlSyncMA Export
CSCRIPT //B %_script_dir%WingTipToysGAlSyncMA_Export.vbs

REM Delta Import
echo ContosoGALSyncMA Delta Import
CSCRIPT //B %_script_dir%ContosoGALSyncMA_Delta_Import.vbs

echo NorthwindGALSyncMA Delta Import
CSCRIPT //B %_script_dir%NorthwindGALSyncMA_Delta_Import.vbs

echo WingTipToysGAlSyncMA Delta Import
CSCRIPT //B %_script_dir%WingTipToysGAlSyncMA_Delta_Import.vbs

 

Create a scheduled task on the MIM Synchronisation Server to run GALSync_RunProfiles.cmd script every 1 hour (or for an interval of your choice). Use the task scheduler account that had been created during the preparation stage to run this scheduled task.

Some Gotchas

I have found that sometimes some mailboxes fail to be imported into the MIM Metaverse and report an mv-constraing-restriction violation on the msExchSafeSenderHash attribute. This error occurs because the AD attribute msExchSafeSenderHash is much longer than what the corresponding MIM Metaverse attribute is. Since this attribute is not being used to create the contacts in the other Exchange Forests, it can be dropped from the attribute flow.

Use the steps outlined in the following article to resolve this issue. https://social.technet.microsoft.com/wiki/contents/articles/10733.troubleshooting-galsync-mv-constraint-violation-msexchsafesenderhash.aspx

 

I hope this blog helps those that might be wanting to create a shared “global address book” among multiple Exchange Forests.

As mentioned previous, the above steps can be used to create a  shared “global address book” for two Exchange Forests as well. In that case, just remove any mention of the third AD Forest, AD Domain and Exchange Forest from the above mentioned steps.

Enjoy 😉

Identifying Active Directory Users with Pwned Passwords using Microsoft/Forefront Identity Manager v2, k-Anonymity and Have I Been Pwned

Background

In August 2017 Troy Hunted released a sizeable list of Pwned Passwords. 320 Million in fact.

I subsequently wrote this post on Identifying Active Directory Users with Pwned Passwords using Microsoft/Forefront Identity Manager which called the API and sets a boolean attribute in the MIM Service that could be used with business logic to force users with accounts that have compromised passwords to change their password on next logon.

Whilst that was a proof of concept/discussion point of sorts AND  I had a disclaimer about sending passwords across the internet to a third-party service there was a lot of momentum around the HIBP API and I developed a solution and wrote this update to check the passwords locally.

Today Troy has released v2 of that list and updated the API with new features and functionality. If you’re playing catch-up I encourage you to read Troy’s post from August last year, and my two posts about checking Active Directory passwords against that list.

Leveraging V2 (with k-Anonymity) of the Have I Been Pwned API

With v2 of the HIBP passwod list and API the number of leaked credentials in the list has grown to half a billion. 501,636,842 Pwned Passwords to be exact.

With the v2 list in conjunction with Junade Ali from Cloudflare the API has been updated to be leveraged with a level of anonymity. Instead of sending a SHA-1 hash of the password to check if the password you’re checking is on the list you can now send a truncated version of the SHA-1 hash of the password and you will be returned a set of passwords from the HIBP v2 API. This is done using a concept called k-anonymity detailed brilliantly here by Junade Ali.

v2 of the API also returns a score for each password in the list. Basically how many times the password has previously been seen in leaked credentials lists. Brilliant.

Updated Pwned PowerShell Management Agent for Pwned Password Lookup

Below is an updated Password.ps1 script for the previous API version of my Pwned Password Management Agent for Microsoft Identity Manager. It functions by;

  • taking the new password received from PCNS
  • hashes the password to SHA-1 format
  • looks up the v2 HIBP API using part of the SHA-1 hash
  • updates the MIM Service with Pwned Password status

Checkout the original post with all the rest of the details here.

Summary

Of course you can also download (recommended via Torrent) the Pwned Password dataset. Keep in mind that the compressed dataset is 8.75 GB and uncompressed is 29.4 GB. Convert that into an On-Premise SQL Table(s) as I did in the linked post at the beginning of this post and you’ll be well in excess of that.

Awesome work from Tory and Junade.

 

Automating the generation of Microsoft Identity Manager Configuration Documentation

Introduction

Last year Microsoft released the Microsoft Identity Manager Configuration Documenter which is available here. It is a fantastic little tool from Microsoft that supersedes its predecessor from the Microsoft Identity Manager 2003 Resource Toolkit (which only documented the Sync Server Configuration).

Running the tool (a PowerShell Module) against a base out-of-the-box reference configuration for FIM/MIM Servers reconciled against an exported configuration from the MIM Sync and Service Servers from an implementation, generates an HTML Report document that details the existing configuration of the MIM Service and MIM Sync.

Overview

Last year I wrote this post based on an automated solution I implemented to perform nightly backups of a FIM/MIM environment during development.

This post details how I’ve automated another daily task for a large development environment where a number of changes are going on and I wanted to have documentation generated that detailed the configuration for each day. Partly to quickly be able to work out what has changed when needing to roll back/re-validate changes, and also to have the individual configs from each day so they could also be used if we need to rollback.

The process uses an Azure Function App that uses Remote PowerShell into MIM to;

  1. Leverage a modified (stream lined version) of my nightly backup Azure Function to generate the Schema.xml and Policy.xml MIM Service configuration files and the Lithnet MIIS Automation PowerShell Module installed on the MIM Sync Server to export of the MIM Sync Server Configuration
  2. Create a sub-directory for each day under the MIM Documenter Tool to hold the daily configs
  3. Execute the generation of the Report and have the Report copied to the daily config/documented solution

Obtaining and configuring the MIM Configuration Documenter

Download the MIM Configuration Documenter from here and extract it to somewhere like c:\FIMDoco on your FIM/MIM Sync Server. In this example in my Dev environment I have the MIM Sync and Service/Portal all on a single server.

Then update the Invoke-Documenter-Contoso.ps1 (or whatever you’ve renamed the script to) to make the following changes;

  • Update the following lines for your version and include the new variable $schedulePath and add it to the $pilotConfig variable. Create the C:\FIMDoco\Customer and C:\FIMDoco\Customer\Dev directories (replace Customer with something appropriate.
######## Edit as appropriate ####################################
$schedulePath = Get-Date -format dd-MM-yyyy
$pilotConfig = "Customer\Dev\$($schedulePath)" # the path of the Pilot / Target config export files relative to the MIM Configuration Documenter "Data" folder.
$productionConfig = "MIM-SP1-Base_4.4.1302.0" # the path of the Production / Baseline config export files relative to the MIM Configuration Documenter "Data" folder.
$reportType = "SyncAndService" # "SyncOnly" # "ServiceOnly"
#################################################################
  • Remark out the Host Settings as these won’t work via a WebJob/Azure Function
#$hostSettings = (Get-Host).PrivateData
#$hostSettings.WarningBackgroundColor = "red"
#$hostSettings.WarningForegroundColor = "white"
  • Remark out the last line as this will be executed as part of the automation and we want it to complete silently at the end.
# Read-Host "Press any key to exit"

It should then look something like this;

Azure Function to Automate execution of the Documenter

As per my nightly backup process;

  • I configured my MIM Sync Server to accept Remote PowerShell Sessions. That involved enabling WinRM, creating a certificate, creating the listener, opening the firewall port and enabling the incoming port on the NSG . You can easily do all that by following my instructions here. From the same post I setup up the encrypted password file and uploaded it to my Function App and set the Function App Application Settings for MIMSyncCredUser and MIMSyncCredPassword.
  • I created an Azure PowerShell Timer Function App. Pretty much the same as I show in this post, except choose Timer.
    • I configured my Schedule for 6am every morning using the following CRON configuration
0 0 6 * * *
  • I also needed to increase the timeout for the Azure Function as generation of the files to execute the report and the time to execute the report exceed the default timeout of 5 mins in my environment (19 Management Agents). I increased the timeout to the maximum of 10 mins as detailed here. Essentially added the following to the host.json file in the wwwroot directory of my Function App.
{
 "functionTimeout": "00:10:00"
}

Azure Function PowerShell Timer Script (Run.ps1)

This is the Function App PowerShell Script that uses Remote PowerShell into the MIM Sync/Service Server to export the configuration using the Lithnet MIIS Automation and Microsoft FIM Automation PowerShell modules.

Note: If your MIM Service is on a different host you will need to install the Microsoft FIM Automation PowerShell Module on your MIM Sync Server and update the script below to change references to http://localhost:5725 to whatever your MIM Service host is.

Testing the Function App

With everything configured, manually running the Function App and checking the output window if you’ve configured everything correct will show success in the Logs as shown below. In this environment with 19 Management Agents it takes 7 minutes to run.

Running the Azure Function.PNG

The Report

The outcome everyday just after 6am is I have (via automation);

  • an Export of the Policy and Schema Configuration from my MIM Service
  • an Export of the MIM Sync Server Configuration (the Metaverse and all Management Agents)
  • I have the MIM Configuration Documenter Report generated
  • If I need to rollback changes I have the ability to do that on a daily interval (either for a MIM Service change or an individual Management Agent change

Under the c:\FIMDoco\Data\Customer\Dev\Report directory is the HTML Configuration Report.

Report Output.PNG

Opening the report in a browser we have the configuration of the MIM Sync and MIM Service.

Report

 

Provisioning Hybrid Exchange/Exchange Online Mailboxes with Microsoft Identity Manager

Introduction

Working for Kloud all our projects involve Cloud services, and all our customers have varying and unique requirements. Recently one of our customers embarked on their migration from On-Premise Exchange to Exchange Online. Nothing really groundbreaking there though, however they had a number of unique requirements including management of Litigation Hold. And that needed to be integrated with their existing Microsoft Identity Manager implementation (that currently provisions new users to their Exchange 2013 environment). They also required that management of the Exchange environment still be possible via the Exchange Management Console against a local Exchange server. This post details how I integrated the environments using MIM.

Overview

In order to integrate the Provisioning and Lifecycle management of Exchange Online Mailboxes in a Hybrid Exchange with Microsoft Identity Manager I created a custom PowerShell Management Agent simply because it was going to provide the flexibility I needed.

Provisioning is based on the following process;

  1. MIM Creates new user in Active Directory (no changes to existing MIM provisioning process)
  2. Azure Active Directory Connect synchronises the user to Azure Active Directory
  3. The Exchange Online MIM Management Agent sees the corresponding AAD account for the new user
  4. MIM Declarative Rules trigger the creation of a new Remote Mailbox for the AD/AAD user against the local Exchange 2013 On Premise Server. This allows the EMC to be used to manage mailboxes On Premise even though the mailbox resides in Office365/Exchange Online
  5. AADC/Exchange synchronises the information as part of the Hybrid Exchange topology
  6. MIM sees the EXO Mailbox configuration for the new user and enables Litigation Hold against the EXO Mailbox (if required)

The following diagram graphically depicts this process.

EXO IDM Provisioning Solution.png

Exchange Online PowerShell MA

As always I’m using my favourite PowerShell Management Agent, the Grandfeldt PS MA now available on Github here.

Schema Script

The Schema script configures the schema required for current and future EXO management requirements. The Schema is based on a single Object Class “MailUser” but pulls the information from a combination of Azure AD User and Exchange Online Mailbox object classes for an associated account. Azure AD User objects are prefixed by ‘AAD’. Non AAD prefixed attributes are EXO Mailbox attributes.

Import Script

The Import script connects to both Azure AD and Exchange Online to retrieve Azure AD User accounts and if present the associated mailbox for a user.

It retrieves all Member AAD User Accounts and puts them into a Hash Table. Connectivity to AAD is via the AzureADPreview PowerShell module. It retrieves all Mailboxes and puts them into a Hash Table. It then processes all the mailboxes first including the associated AAD User account (utilising a join via userPrincipalName).

Following processing all mailboxes the remainder of the AAD Accounts (without mailboxes) are processed.

Export Script

The Export script performs the necessary integration against OnPremise Exchange Server 2013 for Provisioning and Exchange Online for the rest of management. Both utilise Remote Powershell. It also leverages the Lithnet MIIS Automation PowerShell Module to query the Metaverse to validate current object statuses.

Wiring it all up

The scripts above will allow you to integrate a FIM/MIM implementation with AAD/EXO for management of users EXO Mailboxes. You’ll need connectivity from the MIM Sync Server to AAD/O365 in order to manage them.  Everything else I wired up using a few Sets, Workflows, Sync Rules and MPR’s.