moving distribution list memberships from contact to user object with sync engine

We only have the FIM sync engine and when replacing an AD contact object with a user object I am being asked to move the distribution lists that the contact is a member of over to the new user object. I've done the contact to user replacement provisioning many times before but never had to migrate the group memberships over.

Does anyone have any advice for the best approach to do this?



  • Edited by StevenJ. _ Tuesday, March 17, 2015 9:49 PM
March 17th, 2015 9:31pm

Here is one thing I can think of.

1. Join both contact and user to the same MV object. 

2. Write a custom class or method that does the following.  There are plenty of samples out there.

           -> Get a list of DLs contact is a member of

           -> Add user to those groups

3. Lastly, make the contact to user changes.

Free Windows Admin Tool Kit Click here and download it now
March 18th, 2015 9:40am

I have done contact to user conversions for years within FIM provisioning code (just provision the user connector and deprovision the contact connector). I just never have had to transfer the group memberships. And we don't manage groups in FIM so I don't want to have to import them to transfer the memberships. So the learning curve is in how to interact with the DirectoryServices class to read the groups off the contacts and then add the user object to those same groups. Haven't done that before. I'm sure it's easy but since it's new to me, it's taking a while to get up to speed.

Here's another question. I hadn't thought that the user object won't be exported yet when it is provisioned in FIM so I can't add it as a member of the groups during provisioning. Haven't thought about how to do that yet, but any ideas are appreciated.

March 24th, 2015 1:02pm

Hi Steve,

Can you please show me how you are doing the conversion. I am concerned with the time factor.  When things are happening.

Free Windows Admin Tool Kit Click here and download it now
March 24th, 2015 2:41pm

To do the conversion, it's just standard provisioning. I run through whatever tests are needed to determine if the person should have a user object and, if so, I provision a user object and then deprovision the contact. Not sure if that's what you're asking??
March 24th, 2015 3:30pm

This is what I suspected.  You are not doing conversions.  You are simply Deprovisioning contact and provisioning user. For all intends and purposes, the 2 objects are not related in any shape of form.  So how do you know that this contact is related to that user?? 

What you need is, to have both objects connected at the same time in MV before contact is deprovisioned.  Only this way you know that user 'U' is the same as contact 'C'.  FIM needs to know this.

For this, you need to have one MV object with 2 AD connectors, one for user and one for contact. You can use to MAs, or you can use code to have one object with 2 connectors.  (Usually this is not allowed, but with code you can pass this)

Before deprovisioning contact, you do the group membership changes, then you deprovision contact. 

Free Windows Admin Tool Kit Click here and download it now
March 24th, 2015 3:39pm

If indeed, you do have the contact and user at the same time in MV, you can do the group transfer right before calling Deprovision() method.

The code for this is external to FIM,

SUDO Code in MVExtension.DLL

-------

FindGroupMembership

for each group (add user to group)

End Of Loop

Deprovision(contact)

March 24th, 2015 3:51pm

I am doing it just as you described. No problem there. I need to do your last sentence, "you do the group membership changes." That's where I need the how to detail.
Free Windows Admin Tool Kit Click here and download it now
March 24th, 2015 4:47pm

Yep, I understand the process you're describing. Just not the detailed code yet.

Anyway, my bigger question now is how can I add a user object to the AD groups when the user object doesn't yet exist in AD? It's only been provisioned in the connector space but not exported. Trying to figure out a way to do that. Or am I missing something there?

March 24th, 2015 4:53pm

I have done contact to user conversions for years within FIM provisioning code (just provision the user connector and deprovision the contact connector). I just never have had to transfer the group memberships. And we don't manage groups in FIM so I don't want to have to import them to transfer the memberships. So the learning curve is in how to interact with the DirectoryServices class to read the groups off the contacts and then add the user object to those same groups. Haven't done that before. I'm sure it's easy but since it's new to me, it's taking a while to get up to speed.

Here's another question. I hadn't thought that the user object won't be exported yet when it is provisioned in FIM so I can't add it as a member of the groups during provisioning. Haven't thought about how to do that yet, but any ideas are appreciated.

  • Edited by StevenJ. _ Tuesday, March 24, 2015 5:12 PM
Free Windows Admin Tool Kit Click here and download it now
March 24th, 2015 5:00pm

1. No you cannot ad user to group if user is not present. The code acts works directly in AD.  Do not DEprovision contact, until you have fully managed user.  You may need some flags in MV to keep track of things, or use Utils.TransationProperties to store values

2. I do not have something that does 100% exactly what you need, so you need to tweak and test.

3. Here is a sample for finding AD membership.

   #region
 
 
 
getGroupMembership

       
 
 
publicstaticArrayListAttributeValuesMultiString(stringattributeName, stringobjectDn, ArrayListvaluesCollection, boolrecursive)

        {

           
 
 
DirectoryEntryent = newDirectoryEntry(objectDn);

           
 
 
PropertyValueCollectionValueCollection = ent.Properties[attributeName];

           
 
 
IEnumeratoren = ValueCollection.GetEnumerator();

           
 
 
while(en.MoveNext())

            {

               
 
 
if(en.Current != null)

                {

                   
 
 
if(!valuesCollection.Contains(en.Current.ToString()))

                    {

                        valuesCollection.Add(en.Current.ToString());

                       
 
 
if(recursive)

                        {

                            AttributeValuesMultiString(attributeName,
 
 
"LDAP://"+

                            en.Current.ToString(), valuesCollection,
 
 
true);

                        }

                    }

                }

            }

            ent.Close();

            ent.Dispose();

           
 
 
returnvaluesCollection;

        }

    

        
 
 
publicstatic  ArrayListGroups(stringuserDn, boolrecursive)

         {

           
 
 
ArrayListgroupMemberships = newArrayList();

           
 
 
returnAttributeValuesMultiString("memberOf", userDn, groupMemberships, recursive);

         }

 
         #endregion
 
 
 
getGroupMembership


4. Here is the code to add user to group

 
 
publicstaticvoidAddUserToADgroup(stringuserDn, stringgroupDn)

        {
DirectoryEntrydirEntry = newDirectoryEntry("LDAP://"+ groupDn);

                    dirEntry.Properties[
 
 
"member"].Add(userDn);

                    dirEntry.CommitChanges();

                    dirEntry.Close();

                }

       


5. This sample uses DN, so here is how you get DN

 
 
 
publicstaticstringgetDN(objectClassobjectCls, returnTypereturnValue, stringobjectName, stringLdapDomain)

        {

       
 
 
stringdistinguishedName = string.Empty;

       
 
 
stringconnectionPrefix = "LDAP://"+ LdapDomain;

       
 
 
DirectoryEntryentry = newDirectoryEntry(connectionPrefix);

       
 
 
DirectorySearchermySearcher = newDirectorySearcher(entry);

       

        mySearcher.Filter =
 
 
"(&(objectClass="+objectCls+")(|(sAMAccountName="+ objectName + ")))";

       

       
 
 
SearchResultresult = mySearcher.FindOne();

       

       
 
 
if(result == null)

        {

           
 
 
thrownewNullReferenceException

 
                (
 
 
"unable to locate the distinguishedName for the object "+ objectName + " in the "+ LdapDomain + " domain");

        }

       
 
 
DirectoryEntrydirectoryObject = result.GetDirectoryEntry();

       
 
 
if(returnValue.Equals(returnType.distinguishedName))

        {

            distinguishedName = directoryObject.Properties[
 
 
"distinguishedName"].Value.ToString();

        }

        entry.Close();

        entry.Dispose();

        mySearcher.Dispose();

       
 
 
returndistinguishedName;

        }

       
 
 
publicenumobjectClass

 
        {

            user, group

        }

       
 
 
publicenumreturnType

 
        {

            distinguishedName

        }


Nosh Mernacaj, Identity Management Specialist

March 24th, 2015 6:25pm

This topic is archived. No further replies will be accepted.

Other recent topics Other recent topics