In April 2015 the licensing model for FIM is changing. Basically you can say that FIM synchronization service is now free!
Read this blog by Peter Geelen for more information, or download the Microsoft Product Use Rights (WW, English, April 2015) document.
Tag: FIM
FIM 2010 R2 Pre-Requisites
Installing a complete FIM 2010 R2 environment is not an easy task. Lots of things can go wrong. A FIM setup might use almost any number of servers for example. In this post I give you access to scripts and configuration files required to do all FIM 2010 R2 pre-requisites in a typical 4-server FIM deployment.
In the FIMScriptsAndCode.zip you will find PowerShell scripts to create service accounts, configure Kerberos, configure SQL ports and aliases among other things. You will also find ini-files to perform unattended setups of the SQL servers used by FIM. Basically everything you need to do before you can start the installation of FIM.
In the Installation folder in the download package you will find a ReadMeFIRST.txt file that explains the order to perform the steps. Please note that many of the scripts and configuration files used requires editing to match the target environment.
In the RulesExtension folder you will find a simple code example showing how to use rules extension in FIM to import the last logon timestamp from AD into FIM. This is one of the things I show in my FIM 2010 R2 Video Course and this is to give the viewers of that a chance to download the example.
FIM 2010 Video – Released
Finally my video course on FIM 2010 R2 is released.
Read all about it at FIM 2010 R2 Video.
As a teaser I give you this sample.
FIM Team User Group presentation
At the FIM Team User Group meeting in March I held a session about how to use less code in FIM solutions.
If you have any questions regarding this session please comment on this post.
Finding Managers in FIM 2010
When working with FIM 2010 we often use Reference attributes like the Manager attribute. But in FIM we cannot create a corresponding Set with all referenced Managers. The xPath query simply doesn’t allow this kind of referenced object lookup.
So what if I would like a Set or a Group containing all Managers! How do we solve that problem?
In this post I will show you one way of doing this, but please remember that there are many variations of this you could use.
Add IsManager to Schema
First we add a new boolean attribute “IsManager” to the schema in FIM. Depending on how you plan to use this you might need to add it to both the FIM Service and the FIM Synchronization Service schema.
This step I hope you all know involves creating a binding as well as adding the new attribute to the Filter Permissions.
You will also need to add it to some MPR’s to allow the management of this new attribute.
Ones we have this new boolean attribute creating a Set and/or a Group is now reduced to look at this boolean value.
Manage the IsManager flag
The problem is now to have some kind of activity that sets the IsManager attribute to “true” when a manager is configured on a user.
This can be done using a PowerShell WorkFlow activity. I show you a solution working with the PowerShell Workflow Activity you can download from codeplex.. The PowerShell I use in the activity can be downloaded UpdateIsManager.
PowerShell Activity
Let’s look at the PowerShell script I use to understand what it does and how it works.
First we set the basics like URI and load the FIMAutomation snapin.
set-variable -name URI -value "http://localhost:5725/resourcemanagementservice' " -option constant if(@(get-pssnapin | where-object {$_.Name -eq "FIMAutomation"} ).count -eq 0) {add-pssnapin FIMAutomation}
We then get the object that has been changed. Note that I use the “/*” in the xPath since I get the object based on ObjectID I cannot get duplicates and don’t need to specify the object type.
$exportObject = export-fimconfig -uri $URI -onlyBaseResources -customconfig ("/*[ObjectID='{0}']" -F $fimwf.TargetID.Guid)
From the modified user we read the Manager attribute to get the “target” for our change.
$target = $exportObject.ResourceManagementObject.ResourceManagementAttributes | Where-Object {$_.AttributeName -eq "Manager"}
We then build the importChange to set the IsManager attribute to true.
$importChange = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportChange $importChange.Operation = 1 $importChange.AttributeName = "IsManager" $importChange.AttributeValue = $true $importChange.FullyResolved = 1 $importChange.Locale = "Invariant"
Finally we import the change on the target user
$importObject = New-Object Microsoft.ResourceManagement.Automation.ObjectModel.ImportObject $importObject.ObjectType = "Person" $importObject.TargetObjectIdentifier = $target.Value $importObject.SourceObjectIdentifier = $target.Value $importObject.State = 1 $importObject.Changes = (,$importChange) $importObject | Import-FIMConfig -uri $URI
If you apply this logic to a MultiValue reference attribute the script needs to be extended with a loop like the one below to apply the change to all referenced objects.
ForEach($value in $target.Values)
The importObject’s ObjectIdentifier would than just be $value within the loop.
The MPR
The MPR to trigger this Workflow is just a simple Request MPR that fires whenever someone changes the Manager attribute on any user.
What about deletes?
As you can see this solution will only make sure that the IsManager is set to true for all referenced managers. But it will not set it to “false” if they are no longer referenced. The problem is that if you were to detect the deletion of a manager you cannot set it to false since it might be referenced on other users. Doing that lookup, to verify this was the “last” reference, is quite costly from a resource perspective and I don’t think it’s a good idea to do it as part of the WorkFlow activity.
I think that a good approach to set the IsManager to “false” is to have a maintenance job running a PowerShell that verifies that all IsManager=”true” indeed still are referenced. That PowerShell will however have to wait for another post, another time.
Summary
Adding small boolean flags to the schema makes filters in Set’s, Group’s and Synchronization Rules very easy to implement. Using a PowerShell Workflow Activity is often the easiest and quickest way of solving workflow needs to make sure these boolean flags are kept up-to-date in FIM 2010.
FIM 2010 R2 4.1.3496.0 introduces error event when searching the portal
After you have updated your FIM 2010 R2 Service & Portal to 4.1.3496.0 you will start to get errors in the eventlog every time someone makes a search in the FIM Portal. This is due to a new feature added in this update that gives you the ability to hide the advanced search option.
The error you will get in the Forefront Identity Management application log is “System.Collections.Generic.KeyNotFoundException: The given key was not present in the dictionary.”
This error is due to the new feature, described in the 4.1.3496.0 KB article, allowing you to hide the advanced search option.
Solution
To get rid of this error you need to follow the instructions in the KB article and add the boolean HideAdvancedSearchLink attribute and bind it to the Portal Configuration resource.
This will get rid of the error message, but in order to use the new feature and manage it you would also need to add the MPR allowing Administrators to set the value.
Credit
This solution I found as an answer in the TechNet forum. Where the answer was submitted by Andrew Weiss.
Schedule FIM 2010 with a sleep option
When scheduling your run profiles in FIM 2010 you sometimes needs to add a short sleep, to allow for the external system to process data. This can for example be required when the FIM Service needs to apply some workflow on the exported data before you import the result.
In this post I will show you one option to do so when using PowerShell script to run the profiles in FIM Synchronization Service.
The scripts I show you snippets of in this post can be downloaded here: ScheduleFIMwSleep.
DeltaRunWithSleep.ps1
I usually use a PowerShell script to schedule the typical run profiles.
In the script I allow for a special “profile” using the syntax “Sleep:X” to make the script sleep for X seconds.
@{ name="FIMService"; profilesToRun=@("Export";"Sleep:30";"Delta Import";"Delta Sync"); };
So whenever it finds this “Sleep” profile it will sleep instead of trying to run an actual run profile.
if($profileName.StartsWith("Sleep")) {Start-Sleep -Seconds $profileName.Split(":")[1]} else { $result = $MA.Execute($profileName); if("success".Equals($result.ReturnValue)){} else {$msg = "Error: "+$result} }
ReloadWithSleep.ps1
A special case of run schedule is when you need to do some kind of reload or initial load of data. This could be just because you deleted a connector space and need to reload or when changing configuration.
If you use this due to migrating or changing configuration you should be aware that you should always run Full Synchronization rather than Delta on all MA’s with configuration changes.
In this run profile I have added that it disables provisioning before running any run profiles and then enables it once it’s done.
#Disable Provisioning & "$scriptpath/DisableProvisioning.ps1" #Run Profiles do {….} #EnableProvisioning & "$scriptpath/EnableProvisioning.ps1"
As you can see the actual enabling and disabling is made in two separate PowerShell scripts (EnableProvisioning.ps1 and DisableProvisioning.ps1) that need to reside in the same folder as the script calling.
Hopefully the information in this post makes your scheduling of FIM 2010 easier.
Using a CleanUp MA in FIM 2010
Every now and then a FIM administrator runs into having to do some cleanup in the MetaVerse in FIM. It could be things like deleting objects or “nulling” attributes.
In this post I will show you how you can use a CleanUp MA to assist you in this task. The example I use is to delete all group objects that are missing the accountName attribute.
There are several ways of creating the CleanUp MA. My approach is to use a SQL MA that uses a SQL view of the MetaVerse to filter the objects you would like to “Clean Up”.
WARNING! Before you continue make sure all schedules are turned off and that you make a new backup of the FIMSynchronizationService database.
First let’s create the SQL view. The table you use in the view is the mms_metaverse and the “required” attributes you should use is the object_id and object_type. Object_id is the one you use to join and object_type is for defining the object_type column in the SQL MA. You then add columns and filters as needed to define the objects in the MV that you need to work with. In this example I take group objects where accountName is missing.
Then create a simple SQL MA using the view and create a join rule using the object_id attribute.
Configure run profiles for Full Import and Full Synchronization
Run Full Import and Full Sync to join the objects in the CleanUp MA to the objects in the MV.
In Metaverse Designer configure a new object deletion setting to delete group objects if they are disconnected from the CleanUp MA.
If you would like to propagate the deletion to another MA (or MA’s) you can temporary define the deprovisioning setting on that MA to delete objects when disconnected. In my example these groups has an error in the FIM Service MA since they lack the required accountName. These pending provisions will be deleted once the MV object is deleted.
To fire off the deletion just delete the connector space of the CleanUp MA. This will now disconnect and delete the MV object and, in my case, the pending errors in the FIM Service MA.
When done, remember to reset the object deletion rule and deprovisioning settings you changed to its prior setting.
The CleanUp MA can be kept for future needs. Just change the view as needed and do a Refresh Schema on the CleanUp MA to use it for other purposes when needed.
Building the FIM 2010 R2 SmsServiceProvider.dll
When using Self-Service Password Reset (SSPR) in FIM 2010 R2 it is a common request from my customers to use SMS OTP (One-Time Password) to authenticate the user trying to reset his password.
In one of my earlier posts, Automate SSPR registration in FIM 2010 R2, I described how you can automate the registration process. But in order to use SMS OTP you also need to build a small dll file. At Microsoft TechNet you can find an example on how to build the required SmsServiceProvider.dll.
The problem is that there is a “bug” in the FIM Service that makes it easy to build the dll in a way that does not work. The error you will run into is shown in the eventlog as “System.TypeLoadException: The custom SMS provider DLL does not implement the required interface.“.
The dll is required to have a class that implements the Microsoft.IdentityManagement.SmsServiceProvider.ISmsServiceProvider interface and that class should have a public method called SendSMS as seen in the code snippet below.
namespace XPServices.FIM.SmsServiceProvider { using System; using System.Collections.Generic; using Microsoft.IdentityManagement.SmsServiceProvider; public class SmsServiceProvider : ISmsServiceProvider { public void SendSms(string mobileNumber, string message, Guid requestId, Dictionary<string, object> deliveryAttributes) { XPServices.FIM.mySMSProvider.SendSms(mobileNumber, message); } } }
When the FIM Service looks at the dll it requires that the ISmsServiceProvider is the FIRST interface. If your SMS service provider uses for example a Web Service and you add the reference to that Web Service in your code it will likely show up first and the FIM Service will give you the error “System.TypeLoadException: The custom SMS provider DLL does not implement the required interface.”
The solution is to move all logic and references into a separate class library. As you see in my code above all logic about how to send the SMS is moved into the XPServices.FIM.mySMSProvider class. This will hold the references to any Web Services and FIM Service will not have any trouble enumerating the SmsServiceProvider.dll since it only holds one class and one method. Below is a snippet showing parts of a typical class library in this scenario.
namespace XPServices.FIM { public class mySMSProvider { static string id; static string password; public static string SendSms(string userMobileNumber, string message)… public static void GetSMSConfig()… } }
When deploying this all we need to do is drop both dll’s in the FIM Service folder (default this is C:\Program Files\Microsoft Forefront Identity Manager\2010\Service\)
Redirect to IdentityManagement site in SPF 2013
It’s a common request, when starting to use the FIM 2010 Portal for self-service, to try to redirect the root url of the FIM portal to the IdentityManagement sub-site. If you have moved to SPF 2013 you will find that none of the methods available in easy to find documentation from Microsoft will work.
Using for example the IIS HTTP Redirect as suggested on the TechNet Wiki. Trying this will however mess-up your site since it will affect your CSS.
On the FIM TechNet site there is also a note close to the bottom of the Installing the FIM 2010 R2 Server Components page about “To redirect the FIM Portal”. This will not work either because SPF 2013 just ignores the default.aspx page.
So how should we do it?
After some investigation I found the clue to the solution in a SharePoint forum thread. The solution was presented by Per Jakobsen.
[EDIT 2018-12-13]
I now have a brand new solution to this problem… Please ignore old solution and use my new PowerShell script on Gist.
— old solution below–
This is how I have solved it.
Create a document using notepad and call it, for example, RedirectFIM.aspx. The file should have the following content.
<html> <head> <title>Redirect to IdentityManagement site</title> <meta http-equiv="refresh" content="0; url=https://im.company.com/IdentityManagement/default.aspx" /> </head> <body> </body> </html>
Upload this file as a new document to the Shared Documents library in SharePoint.
You can now try that it is working by clicking on it. You should be redirected to our familiar FIM homepage.
When we know it is working we can set it as homepage for the site. Since this is a subsite we need to use PowerShell to do it.
Start the SharePoint 2013 Management Shell and configure the uploaded page as WelcomePage for the root site.
$w = Get-SPWeb https://im.company.com $root = $w.RootFolder $root.WelcomePage = "Shared%20Documents/RedirectFIM.aspx" $root.Update()
If you now access the root site https://im.company.com you will end up being redirected to the IdentityManagement site. If you need to access the root site you can always use the old default home page at https://im.company.com/SitePages/Home.aspx