SharePoint: Considerations when switching from FIM Sync to AD Import

Many times we end up battling “SharePoint Profile Synchronization” (aka: “FIM Sync”) for a while before we realize that “SharePoint Active Directory Import” (aka: “AD Import”, aka: “ADI”) was a better fit all along.

Why switch?  Or for new farms, why go with AD Import?

“SharePoint Active Directory Import” (“AD Import” from here on) is the preferred and recommended user profile import mechanism for SharePoint 2013 and above.  In fact, in SharePoint 2016, the “FIM Sync” option no longer exists, so if you’re on SharePoint 2013 and still clinging to FIM Sync, you’ll need to start looking into either AD Import or an external identity manager like “Microsoft Identity Manager” (MIM) 2016.

Here are some really good reasons for using AD Import:

  • It’s fast.  I mean, really fast compared to FIM Sync.  Mileage will vary, but in many cases something on the order of 10x faster.
  • There’s no Sync service to battle.  The User Profile Synchronization Service is still there in 2013, but AD Import doesn’t use it, so you don’t have to worry about starting it, which is almost always a pain.
  • It also does not use the Sync database.  Your User Profile Service Application (UPA) will still have a Sync database, but it will remain empty and unused.  All AD Import configuration is stored in the Profile database.
  • Did I mention it’s fast?  That’s usually the seller.  Customers with 500,000+ profiles used to wait a week or more for a Full Sync to complete.  With AD Import, the same Full Import generally takes a day or less.

It's not a free meal.

To be fair, AD Import is not for everyone.  There are some configurations where AD Import just doesn’t have the ability to meet some profile import requirements, and therefore you must use FIM Sync (or an external identity provider if you're using SharePoint 2016).  The list of those drawbacks is in the “Before you begin” section here: https://technet.microsoft.com/en-us/library/jj219646.aspx 

There are a number of things listed there, but we’ve found that the primary limitations that cause customers to go with FIM Sync are the following:

  • AD Import only does Active Directory.  So if you have any 3rd party LDAP provider, you need to use FIM.
  • AD Import is import only.  You can’t export values to AD.
  • AD Import cannot import BDC / BCS data.
  • AD Import cannot import profile pictures.

We’ve found that the profile picture one is a major hang-up, but there are alternative solutions.

 

Important: While it’s perfectly ok to switch an existing UPA from FIM Sync to AD Import, I strongly recommend disabling the My Site Cleanup Job (timer job) until you’ve run through a few AD Imports and are happy with the results.

So now lets assume you’ve decided to switch to AD Import.

Good for you.  However, AD Import does work a bit differently, so here are some additional considerations.  -- These are not necessarily "drawbacks", just differences to be mindful of.

  • The connection filters are implemented differently.  Instead of the FIM exclusion filters, you just set a standard LDAP filter on the import connection page.  Those familiar with LDAP find this a welcome change as it's a standardized syntax.  Not to mention, it's much easier to replicate (just copy and paste) between farms.
    • Note: when using AD Import, the "Edit Connection Filters" drop-down still exists on the import connection.  However, it won't work and throws this error:
    • Like I said, AD Import filters are implemented differently.  You define the LDAP filter on the edit import connection page:

 

  • Troubleshooting is different.  There is no "FIM Client" to look at when things go wrong.  All importing is done by a timer job called "<UPAName> - User Profile Active Directory Import Job".  To figure out what happened with the import, you should be reviewing the SharePoint ULS logs from the server that ran the timer job -- check timer job history first to make sure you have the correct server and correct instance of the timer job.
  • Property mappings look different.  The out-of-box mappings are pretty much the same as when using FIM Sync.  However, it's hard to tell because you can't see them in Central Admin.  I explain in more detail in another post here.
  • "Out of Scope" (deleted, filtered, moved to a non-imported OU) users do not have their profiles automatically cleaned up by an incremental import.  With AD Import, we don't use the Sync database to store "state" information about each user.  As such, the only way AD Import can tell if a user has fallen "out of scope" is to import them.  If the user object has not changed in AD, an incremental import will not pick them up.  Luckily, AD Import is fast, so running a Full import is not a big deal.  For more on this, see this post by one of my colleagues. Also, check out my 4-part series on cleaning up user profiles: https://blogs.technet.microsoft.com/spjr/2018/04/08/sharepoint-the-complete-guide-to-user-profile-cleanup-part1/  
  • You must create one import connection per-domain.  If you have a large AD forest with many trees and domains, you can’t just create one connection at the forest level anymore.  You must create a separate connection for each domain.

Lets talk about that last point a bit more.

If you have a lot of domains, that initial setup can be a bit painful.  To add to that, any custom profile property mappings you do must be done per-import connection.  This means that if you have 10 domains and 10 custom mappings you want to make, you’re making 100 total mappings.  Ouch.  But… once again, PowerShell is your friend.  While there isn’t a really great supported way to use PowerShell to create the import connections for SharePoint on-prem, you certainly can (and should) use it to create the property mappings.

There are several examples out there showing how to create AD Import connection mappings, but I found that none of them really accounted for handling multiple mappings or multiple import connections.  So I wrote one.

A couple of notes about this script:

  • First off, it’s a sample only.  I'm not going to "support" it.  Test it, tweak it, and make it your own.
  • It makes a few assumptions like:
    • If you’re trying to map to custom profile properties, those properties have already been created in the UPA.
    • You are trying to map the same AD attributes to the same profile properties for each domain / import connection.  If you need to make different mappings for one or more domains, this script is not for you as-is, but can still be used as a starting point.
  • It reads AD-Attribute / SharePoint-Property pairs in and creates the mappings.  It also loops through each import connection and makes the same mappings for each connection.
  • The idea here is that after your import connections are created, you could run this script once and all your custom mappings will be made across all import connections.

Here’s what an example input CSV file looks like:

 

Note: The first row (ad,sharepoint) is a “header” row and should be left as is.  The additional rows hold the name of each AD attribute and then the comma-separated name of the SharePoint profile property you want to map it to.

Here’s the SAMPLE script:

 ############################## -- Script -- ##############################
 #Author: Joroar
 #Date: 8/13/17
 #This script is provided as-is with no warranties expressed or implied. Please have good and current backups.
 #USE AT YOUR OWN RISK!
 #Synopsis: Use this to create profile property mappings for Active Directory Import from a list of profile properties and AD attributes stored in a CSV
 #The CSV should have a 'header row' and look something like this with a single AD attribute / SharePoint property pair on each line:
    #  ad,sharepoint
    #  streetaddress,sps-location
    #  givenname,firstname
    #  sn,lastname
 
 #It will also loop thorough each AD Import connection you have and make the same mappings there.
 #Important!  The script assumes that the mappings you want to create have the same AD attribute name in EVERY domain. 
 #If you want to make different mappings for each connection, this script is NOT for you, but could still be a good starting point.
 #The “$URL” variable can really be any site collection in the farm that is associated with the target User Profile Service App.  
 #Just set the top three variables: $url, $path, $logfile

$path = "C:\Temp\mappings\Properties.csv"  #This the the CSV that contains the mappings
$logfile = "C:\Temp\mappings\PropertyMappingLog.txt"  #This is the output log file
$URL = "https://teams.contoso.com" #Any site associated with the UPA

#Shouldn't need to change anything below this line:
Add-PSSnapin microsoft.sharepoint.powershell
$date = Get-Date -Format U
"Started creating property mappings at " + $date + " (UTC time)" | out-file $logfile -append
"=================================================================" | out-file $logfile -append
$ErrorActionPreference = "stop"
$csv = Import-Csv -Path $path
[array]$Properties = @()
foreach($line in $csv)
{$Properties += $line}
$Total = $Properties.Count
$site = get-spsite $url
$context = [Microsoft.SharePoint.SPServiceContext]::GetContext($site)
$configManager = New-Object Microsoft.Office.Server.UserProfiles.UserProfileConfigManager $context
$UPAConnMgr = $configManager.ConnectionManager
foreach($Connection in $UPAConnMgr)
{
"Creating Mappings For Connection: "  + $connection.Displayname | out-file $logfile -Append
Write-host "Creating Mappings For Connection: " $connection.Displayname 
    for($j=0; $j -lt $Total; $j++)
    {   
    $adAttribute = $Properties[$j].ad
    $spsProperty = $Properties[$j].sharepoint
        try{
        "Creating mapping between " + $adAttribute  + " and " + $spsProperty | out-file $logfile -Append
        Write-host "Creating mapping between  $adAttribute and $spsProperty"
        $Connection.AddPropertyMapping($adAttribute,$spsProperty)
        }
        catch [system.Exception]
        {"ERROR!!! adding mapping for property: " + $spsProperty + " -- " + $_.Exception.Message | out-file $logfile -append
        Write-host "we seem to have hit an error.  Check the log file"}
        }
    try{
    $Connection.Update()
    "---------------------------------" | out-file $logfile -Append
    }
    catch [system.Exception]
    {"ERROR!!! updating connection " + $connection.Displayname + $_.Exception.Message | out-file $logfile -append
    Write-host "we seem to have hit an error.  Check the log file"
    }
}
############################## -- Script -- ##############################

More Keywords for Bing:

Forefront Identity Manager FIM

Microsoft Identity Manager MIM

SharePoint Server 2013 2016

Miisclient.exe FIM Client

Active Directory Import AD Import ADI