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
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.
In your bindings in IIS have the Host Name match your certificate.
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.
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.
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.
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 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.
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 multi-way depending on what you are looking to achieve. Essentially this is the Azure equivalent of using FIM/MIM for Global Address List Sync.
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 the Invite Guest users 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.
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.
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’.
With those permissions selected and while authenticated as an Administrator select the Grant Permissions button to assign those permissions to the Application.
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.
Make sure you have ‘Create Resource in FIM‘ configured on the source (or both if doing bi-directional) Graph Connector.
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.
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.
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
Here is an example of building a UPN.
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.
Looking at the Pending Export we can see our rules have applied.
On Export the Guest accounts are successfully created.
On the confirming import we get the rename as Azure has generated a new CN and therefore DN for the Guest user.
Looking into Azure AD we can see one of our new Guest users.
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.
Windows Remote Management (aka Remote PowerShell) is a wonderful thing; when it works straight out of the box when you’re in the same domain. Getting it working across Forests though can feel like jumping through hoop after hoop, and sometimes like the hoops are on fire. When configuring GALSync ([Exchange] Global Address List Synchronisation) with FIM/MIM this always means across AD Forests. The graphic below shows the simplest relationship. If there is a firewall(s) in between then you’ll have additional hoops to jump through.
This article here is the most definitive I’ve found about what is required, but it isn’t easily found even when you know it exists. In the last few months I’ve had to set up GALSync with FIM/MIM a number of times, and I have visibility that I’ll be needing to do it again in the future. So here is my consolidated version of the process using PowerShell to make the configuration changes. If nothing else it’ll help me find it quickly next time I need to do it.
This post assumes you have the other prerequisites all sorted. They are pretty clear in the linked article above such as a One-way Cross Forest Trust, connectivity on the necessary ports if there are firewalls in-between FIM/MIM and the Exchange CAS Server and Domain Controllers in the remote environment.
Configuring Remote PowerShell for FIM/MIM GALSync
My tip is to start from the MIM Sync Server.
Get the details for the Service Account that you have/will specify on your GALSync Active Directory Management Agent that connects to the Remote Forest.
Have that account be given (temporarily) Remote Desktop permissions to the Remote Exchange CAS Server that you will be configuring the Active Directory Management Agent to connect to. Or use another Admin account that has permissions to Remote Desktop into the CAS Server, then …
… start a Remote Terminal Services Session to the Exchange CAS Server in the Remote Forest
On the Exchange CAS Server (non SSL WinRM)
WinRM must have Kerberos authentication enabled
Kerberos requires TCP and UDP port 88 to be opened from the FIM/MIM server to ALL Domain Controllers in the target Forest. Run the following two commands in an elevated (Administrator) Powershell ISE/Shell session to enable Kerberos
Using PowerShell ISE select File => New Remote Powershell Tab
enter the ExchangeCASFQDN for the Computer field
enter the Service Account that you have specified on your GALSync Active Directory Management Agent that connects to the Remote Forest for User name in the format NetBIOSDOMAINName\Username
If you have done everything correctly you will get a remote powershell command prompt on the Exchange CAS host.
To confirm you have all your other Exchange Dependencies correct (and your AD MA Service account has the necessary permissions in Exchange) run the following script line-by-line. If you have configured Remote PowerShell correctly and have met all the prerequisites you should have are remote session into Exchange.
$Creds = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://.customer.com/PowerShell/ -Credential $Creds -Authentication kerberos
# Get a list of Exchange Servers
# Get a list of Mailboxes
# Get a list of Mail Users
# Close and remove the session
Remove Remote Desktop permissions from the Active Directory Management Agent Service Account if you enabled it to configure the Exchange CAS Server.
Recently in a FIM/MIM environment a daily automated process was executing but the task it was performing was dependent on an upstream process that generates a feed, and the schedule for that feed had changed (without notice to me). Needless to say FIM/MIM wasn’t getting the information it needed to process. This got me thinking about notifications.
If you’re anything like me you probably have numerous email accounts and your subconscious has all but programmed itself to ignore “new email” notifications. However Push Notifications I typically do notice. Whilst in the example above I did have some error handling in place if the process completely failed (it is a development environment), I didn’t have anything for partial failures. Anyway it did get me thinking that I’d like to receive a notification if something that should happen didn’t.
This post details using push notifications to advise when expected events don’t transpire. In this particular example, I have an Azure Function App that connects once a day to a FTP Server and retrieves a series of exports and puts them on my FIM/MIM Synchronisation Sever. The Push Notification service I am using is Push Bullet. Push Bullet for free accounts (without a Pro subscription) are limited to 500 pushes per month. That should be more than enough. If I’ve got errors in excess of 500 per month I’ve got much bigger problems.
First up you will need to sign up for Push Bullet. It is very straight forward if you have a Facebook or Google account. As you’re probably wanting multiple people to receive the notifications it would pay to set up a shared Google Account that your team can use to connect to with their devices. Now you have an account head to your new Account Settings page and create an Access Token. Record it for use in the scripts below.
Connecting to the API
Test you can access the Push Bullet API using your Access Token and PowerShell. Update the following script for your Access Token in line 3 and execute. You should see information returned associated with your new Push Bullet account.
Next you will want to install the Push Bullet App on the device(s) you want to get the notification(s) on. I installed it on my Apple iPhone and also installed the Chrome Browser extension.
Using PowerShell we can then query to get the devices connected to the account. In the same PowerShell session you tested the API with above run this API call
If we want a notification to target a particular device we need to provide the Iden value associated with that device. If we don’t specify a target, the push notification will hit all devices. In my example above with two devices registered my iPhone was device two. So the target Iden I could get with;
$iphoneIden = $devices.devices.iden
Push Bullet allows for different notification types (Note, Link and File). Note is the one that’ll I’ll be using. More info on the other types here.
Sending Test Notification
To perform a notification test, update the following script for your Access Token (line 3). I’ve omitted the Device Identifier to send the message to all devices. I also had to logout of the iOS Push Bullet App and log in again to get the notifications to show.
Success. I received the notification on my iPhone and also in my Chrome browser.
Getting back to my requirement of being notified when a job didn’t find what it expected, I updated my PowerShell Function App that is based off this blog post here to evaluate what it processed and if it didn’t find what is expected, it sends me a notification. I already had some error handling in my implementation based off that blog post but it was based on full failure, not partial (which is what I was experiencing whereby only one part of the process wasn’t returning data).
NOTE: I had to also add the ServerCertificateValidationCallback line into my Function App script before calling the API POST to send the notification as I was getting the dreaded following PowerShell Invoke-RestMethod / Invoke-WebRequest error when sending the notification via the Function App. I didn’t get that error on my dev workstation which is a bit weird.
Invoke-WebRequest : The underlying connection was closed: Could not establish trust relationship for the SSL/TLS secure channel.
If you also receive the error above (or you will be sending Push Notifications via Azure Function Apps) insert this line before your invoke-restmethod call.
Essentially this is my first foray into enabling anything for Push Notifications and this post is food for thought on what can be easily enabled within FIM/MIM to give timely visibility to automated scheduled functions when they don’t perform as expected. It was incredibly simple to set up and get working. I see myself enabling more FIM/MIM functions with Push Notifications in the future.
Update:An element of this solution details checking passwords online (using the Have I Been Pwned API). Troy explains succinctly in his blog-post announcing the pwned passwords list why this is a bad idea. If you are looking to implement the concept I detail in this post then WE STRONGLY recommend using a local copy of the pwned password list. THIS POST HERE details using a local SQL Database to hold the Pwned Passwords Datasets and the change to the Management Agent to query the SQL DB instead of the HIBP API.
Troy also extended his HaveIBeenPwned API to include the ability to query as to whether a password has been pwned and is likely to be used in a brute force attack.
Microsoft provide a premium license feature in Azure Active Directory (Azure Active Directory Identity Protection) whereby leaked credential sets are checked and Admins alerted via reports. But what if you aren’t licensed for the Azure AD Premium Features, or you want something a little more customised and you have Microsoft/Forefront Identity Manager? That is what this post covers.
The following diagram looks a little more complicated than what it really is. The essence though is that password changes can come from a multitude of different scenarios. Using Microsoft’s Password Change Notification Service (PCNS) we can capture password changes and send them to Microsoft Identity Manager so that we can synchronise the password to other systems, or for this use case we can lookup to see if the users new password is on the pwned password list.
This post will cover creating the Pwned Password FIM/MIM Management Agent and flagging a boolean attribute in the MIM Service to indicate whether a users password is on the pwned password or not.
There are a few components to this solution depicted above. You will need;
FIM/MIM Synchronisation Server
with an Active Directory Management Agent configured (most likely you will have a Projection Rule on this MA to get your users into the Metaverse)
not shown in the diagram above you will also need the MIM MA configured to sync users from the Metaverse to the MIM Service
FIM/MIM Service and Portal Server (can be on the same server as above)
Getting Started with the Granfeldt PowerShell Management Agent
If you don’t already have it 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.
Four items of note for this solution;
You must have an Export.ps1 file. Even though we’re not doing exports 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 On Premise Active Directory where we will be importing users from to join to our Metaverse so we can pass password changes to this Management Agent
The same account as above will also need to have permissions in the MIM Service as we will be using the account to update the new attribute we are going to create
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\PwnedPWD
With the Granfeldt PowerShell Management Agent downloaded from Codeplex and installed on your FIM/MIM Server we can create our Pwned Password Management Agent.
Creating the Pwned PowerShell Management Agent
On your FIM/MIM Sync Server create a new sub-directory under your Extensions Directory. eg. PwnedPWD in C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions then create a sub-directory under PwnedPWD named Debug. C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions\PwnedPWD\Debug
Copy the following scripts (schema.ps1, import.ps1, export.ps1, password.ps1) and put them into the C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Extensions\PwnedPWD directory
The following schema.ps1 script sets up the object class (user) and a handful of attributes from Active Diretory that will be useful for logic that we may implement in the future based on users password status.
The import.ps1 script connects to Active Directory to import our AD users into the Pwned Password Management Agent so we can join to the Metaverse object already present for users on the Active Directory Management Agent. The user needs to be joined to the Metaverse on our new MA so they are addressable as a target for PCNS.
As detailed earlier, we aren’t using an Export script in this solution.
The Password script receives password changes as they occur from Active Directory and looks up the Have I Been Pwned API to see if the new password is present on the list or not and sets a boolean attribute for the pwned password status in the MIM Service.
On your FIM/MIM Sync Server from the Synchronisation Manager select Create Management Agent from the right hand side pane. Select PowerShell from the list of Management Agents. Select Next.
Give your MA a Name and a Description. Select Next.
Provide the 8.1 style path to your Schema.ps1 script copied from the steps earlier. Provide an AD sAMAccountName and Password that also has permissions to the MIM Service as detailed in the Prerequisites. Select Next.
Provide the paths to the Import.ps1, Export.ps1 and Password.ps1 scripts copied in earlier. Select Next.
Select the user checkbox. Select Next.
Select all the attributes in the list. Select Next.
Create a Join Rule for your environment. eg. sAMAccountName => person:Accountname Select Next.
Create an import flow rule for user:pwdLastSet => person:pwdLastSet. Select Next.
Ensure that Enabled password management is selected, then select Finish.
With the Pwned Password MA created and configured we need to create at least a Stage (Full Import) and Full SyncRun Profiles and execute them to bring in the users from AD and join them to the Metaverse.
This should be something you’re already familiar with.
When running the Synchronisation we get the joins we expect. In my environment PwdLastSet was configured to sync to the MIM Service and hence the Outbound Sync to on the MIM Service MA.
MIM Service Configuration
In the MIM Service we will create a custom boolean attribute that will hold the pwned status of the users password.
Connect to your MIM Portal Server with Administrator privileges and select Schema Management from the right hand side menu.
Select All Attributes then select New
Provide an attribute name (System name) and a Display Name with a Data Type of Boolean. Provide a Description and select Finish
Search for User in Resource Types then select the User checkbox from the search results and select Binding then select New.
In the Resource Type box type User then click the validate field button (the one with the green tick). In the Attribute Type box type Pwned Password then click the validate field button (the one with the green tick). Select Finish
Configure the Active Directory MA to send passwords to the Pwned Passwords MA
On your existing Active Directory Management Agent select Properties. Select Configure Directory Partitions then under Password Synchronization enable the checkbox Enable this partition as a password synchronization source. Select Targets and select your newly created Pwned Password MA. Select Ok then Ok again.
Testing the End to End Pwned Password Check
Now you should have configured;
PCNS including installation of the Active Directory filters
The existing Active Directory Management Agent as a Password Source
The existing Active Directory Management Agent to send password change events to the Pwned Password MA
Select a user in Active Directory Users and Computers, right click the user and select Reset Password.
I first provided a password I know is on the pwned list, Password1
With PCNS Logging enabled on the MIM Sync Server I can see the password event come through.
Checking in the Pwned Password MA debug log we can see in the debug logging for the user we changed the password for and that when it was checked against Have I Been Pwned the password is flagged as pwned.
Note:If you implement the solution in a production environment obviously remove the password from being logged.
In the MIM Portal search for and locate the user the password we just changed the password for.
Select the user. Scroll to the bottom and select Advanced View. Select the Extended Attributes tab. Scroll down and we can see the Pwned Password shows as checked.
Now repeating the process with a password that isn’t in the Pwned Password list. After changing the password in Active Directory Users and Computers the password went through its sync path. The log shows the password isn’t in the list.
And the MIM Portal shows the Boolean value for Pwned Password is now not selected.
Using PCNS and FIM/MIM we can check whether our Active Directory users are using passwords that aren’t in the Pwned Password list.
What we can then do if their password is in the Pwned Password list is a number of things based on what the security policy is and even what type of user it is. You’ll notice that I’ve included additional attributes in the MA that we can flow through the Metaverse and into the MIM Service that may help with some of those decisions (such as adminCount which indicates if the user is an Administrator).
Potentially for Admin users we could create a workflow in the MIM Service that forces their account to change password on next logon. For other users we could create a workflow that sends them a notification letting them know that they should change their password.
Either way, we now have visibility of the state of users passwords. Big thanks to Troy for adding Pwned Passwords to his Have I Been Pwned API.
Reiterating:An element of this solution details checking passwords online (using the Have I Been Pwned API). Troy explains succinctly in his blog-post announcing the pwned passwords list why this is a bad idea. If you are looking to implement the concept I detail in this post then WE STRONGLY recommend using a local copy of the pwned password list.
Today I was performing a standalone installation of the MIM Self Service Password Reset Portals (Enrollment and Reset). These Portals rely on IIS and not the normal prerequisites associated with the MIM Service Portal (SharePoint etc). As such using PowerShell I’d only installed the Web Server Role with the usual dependencies.
On starting the MIM Service and Portal installation I got the dreaded Microsoft Identity Manager Service and Portal Setup Wizard ended prematurely dialog. So straight into debug mode running with an installation log as per the command below.
msiexec /i “f:\Service and Portal\Service and Portal.msi” /l*v c:\temp\install.log
Into the install.log file created from the installation process I see the following.
Looking into the install log I notice the following error.
In a more readable form
SFXCA: Ensure that the proper version of the .NET Framework is installed, or that there is a matching supportedRuntime element in CustomAction.config. If you are binding to .NET 4 or greater add useLegacyV2RuntimeActivationPolicy=true to the element. CustomAction GetIISVersionFromRegistry returned actual error code 1603 (note this may not be 100% accurate if translation happened inside sandbox)
I have .NET Framework 4.5 installed. Could it be MIM 2016 SP1 still needed .NET Framework 3.5 ?
Taking a punt I installed .NET 3.5.
Restarted the Install. Success.
There you go. Even when you’re only looking to have the SSPR Portals installed you need to have .NET Framework 3.5 installed. And FYI I needed to have the Windows Server 2012 R2 media handy to get the sources for .NET Framework 3.5.