none
updating the anchor value for SQL MA from FIM provisioning code RRS feed

  • Question

  • I'm provisioning a record from AD into a SQL table using FIM 2010 R2 Synchronization Engine.

    The provisioning works fine. I'm taking the AD user object and FIM runs the provisioning code to create a record in SQL table. Here is my table design. Basically I'm taking the AD user and FIM is writing a record in SQL for that user. This part is working fine.

    CREATE TABLE [dbo].[tbl_FGPP_Members](
    	[MemberObjectGUID] [varbinary](50) NULL,
    	[MemberDN] [nvarchar](255) NOT NULL,
    	[MemberObjectType] [nvarchar](10) NOT NULL,
    	[Member_ADDomain] [nvarchar](16) NULL,
    	[Member_sAMAccountName] [nvarchar](64) NULL
    ) ON [PRIMARY]

    So on FIM SQL management agent I'm using 'MemberDN' as the anchor attribute. I could have used MemberObjectGuid but for troubleshooting memberDN is better as it contains a string value (distinguished name of the user from AD).

    When an AD account is renamed or moved within an AD domain, it's distinguishedName will change. Since MemberDN is the anchor which is taking the distinguishedName value from AD in the provisioning code, I cannot just create a flow rule to update it. I was told, I could write some code to update it from the MVExtension provisioning code. So here is how I'm trying to do it:

            void IMVSynchronization.Provision (MVEntry mventry)
            {
               ConnectedMA sqlFGPPUser;
    
    
                switch (mventry.ObjectType)
                {
    
    
                    case "FGPPUser100":
                        sqlFGPPUser = mventry.ConnectedMAs["DGROUPS - USERS SQL MA"];
                        mvObjectType = "FGPP100SQLUser";
    
                        if (sqlFGPPUser.Connectors.Count == 0)
                        {
                            createFGPPUsersInSQL(mventry, sqlFGPPUser);
                        }
    
                        else if (sqlFGPPUser.Connectors.Count == 1)
                        {                        
                            updateFGPPUsersInSQL(mventry, sqlFGPPUser);                                            }
                        
    break;
    }
    
    
    
            void updateFGPPUsersInSQL(MVEntry mventry, ConnectedMA sqlFGPPUser)
            {
                CSEntry csentry;
                ReferenceValue dn;
    
                csentry = sqlFGPPUser.Connectors.ByIndex[0];
                dn = sqlFGPPUser.EscapeDNComponent(mventry["ADdistinguishedName"].Value);
    
                if (mventry["ADdistinguishedName"].Value.ToLower() != csentry.DN.ToString().ToLower())
                {
                    try
                    {
                        csentry.DN = dn;
                    }
                    catch (Exception Ex)
                    {
                        throw new Exception("Exception Message: Exception encountered while renaming the MemberDN " + Ex.Message.ToString());
                    }
                }
            }
    

    However, when I rename the AD user and import and then run sync run profile, I get the following error:

    System.Exception: Exception Message: Exception encountered while renaming the MemberDN attribute MemberDN is read-only
       at Mms_Metaverse.MVExtensionObject.updateFGPPUsersInSQL(MVEntry& mventry, ConnectedMA& sqlFGPPUser) in D:\FIM C# Code\FGPP100\FGPP100\MVExtension\MVExtension.cs:line 526
       at Mms_Metaverse.MVExtensionObject.Microsoft.MetadirectoryServices.IMVSynchronization.Provision(MVEntry mventry) in D:\FIM C# Code\FGPP100\FGPP100\MVExtension\MVExtension.cs:line 566

    What am I doing wrong? :(


    • Edited by gtrivedi1980 Thursday, June 18, 2015 5:32 PM correction
    Thursday, June 18, 2015 5:29 PM

All replies

  • As far as I know you cannot write to anchor attribute. That is read only. 

    Nosh Mernacaj, Identity Management Specialist

    Thursday, June 18, 2015 7:10 PM
  • Thanks Nosh,

    Is there some way I can create a new connector and delete the old one from SQL MA Connector space?

    I've tried the following (when I detect that the distinguishedName on metaverse object is different from whats on the SQL MA CS object, I try to call the csentry.deprovision and try creating a brand new connector.

            void createFGPPUsersInSQL(MVEntry mventry, ConnectedMA sqlFGPPUser, string mvObjectType)
            {
                CSEntry csentry;
                csentry = sqlFGPPUser.Connectors.StartNewConnector(mvObjectType);
                csentry["MemberDN"].Value = mventry["ADdistinguishedName"].Value;
    
                try
                {
                    csentry.CommitNewConnector();
                }
                catch (System.Exception Ex)
                {
                    throw new UnexpectedDataException(Ex.Message);
                }
            }
    
    
            void updateFGPPUsersInSQL(MVEntry mventry, ConnectedMA sqlFGPPUser)
            {
                CSEntry csentry;
                ReferenceValue dn;            
    
                csentry = sqlFGPPUser.Connectors.ByIndex[0];
                dn = sqlFGPPUser.EscapeDNComponent(mventry["ADdistinguishedName"].Value);           
    
                // Check to see if the distinguishedName flowing from AD has changed...
                if (mventry["ADdistinguishedName"].Value.ToLower() != csentry.DN.ToString().ToLower())
                {
                    // disconnect the old object.
                    csentry.Deprovision();
    
                    // Now try creating a brand new connector.
                    if (mventry.ObjectType == "FGPPUser100")
                    {
                        ConnectedMA NewSQLFGPPUser;
                        NewSQLFGPPUser = mventry.ConnectedMAs["DGROUPS - USERS SQL MA"];
    
                        if (NewSQLFGPPUser.Connectors.Count == 0)
                        {
                            createFGPPUsersInSQL(mventry, NewSQLFGPPUser, "FGPP100SQLUser");
                        }
    
                    }
                }
            }
    
    
            void IMVSynchronization.Provision (MVEntry mventry)
            {
    			//
    			// TODO: Remove this throw statement if you implement this method
    			//
    
      
                ConnectedMA sqlFGPPUser;
                string mvObjectType = null;
    
                switch (mventry.ObjectType)
                {
    
    
                    case "FGPPUser100":
                        sqlFGPPUser = mventry.ConnectedMAs["DGROUPS - USERS SQL MA"];
                        mvObjectType = "FGPP100SQLUser";
    
                        if (sqlFGPPUser.Connectors.Count == 0)
                        {
                            createFGPPUsersInSQL(mventry, sqlFGPPUser, mvObjectType);
                        }
    
                        else if (sqlFGPPUser.Connectors.Count == 1)
                        {                        
                            updateFGPPUsersInSQL(mventry, sqlFGPPUser);  
                        }
                        break;
    }
    }
    
    

    However, I get an error like this on Sync run.

    Microsoft.MetadirectoryServices.UnexpectedDataException: An object with DN "CN=FGPP-EYIAM-USER-01\,OU=FIM user rename OU\,OU=Dynamic Groups\,OU=FIM 2010 R2\,DC=eyiam\,DC=net" already exists in management agent "DGROUPS - USERS SQL MA".
       at Mms_Metaverse.MVExtensionObject.createFGPPUsersInSQL(MVEntry mventry, ConnectedMA sqlFGPPUser, String mvObjectType) in D:\FIM C# Code\FGPP100\FGPP100\MVExtension\MVExtension.cs:line 498
       at Mms_Metaverse.MVExtensionObject.updateFGPPUsersInSQL(MVEntry mventry, ConnectedMA sqlFGPPUser) in D:\FIM C# Code\FGPP100\FGPP100\MVExtension\MVExtension.cs:line 523
       at Mms_Metaverse.MVExtensionObject.Microsoft.MetadirectoryServices.IMVSynchronization.Provision(MVEntry mventry) in D:\FIM C# Code\FGPP100\FGPP100\MVExtension\MVExtension.cs:line 568

    If I look at the connector space of SQL, I do see an object but it has the

    Notice the DN is different from whats in the error message. [this part: OU=FIM user rename OU]

    After the move in ad, the objects correct distinguishedname is:

    CN=FGPP-EYIAM-USER-01,OU=FIM user rename OU,OU=Dynamic Groups,OU=FIM 2010 R2,DC=eyiam,DC=net

    Any help will be greatly appreciated.

    Thanks.

    GT

    Thursday, June 18, 2015 10:27 PM
  • There is a way. A much easier way. All you need to do is deprovisiob old objet. New one will be created automatically. So on Metaverse you set deletion rule to say when ad ma is disconected, delete mv object. Then on sql ma you select delete connector under deprovisioning options.

    Nosh Mernacaj, Identity Management Specialist

    Thursday, June 18, 2015 11:26 PM
  • But, why do you go this route anyways. Why dont you flow sAMAccountName or another attribute that does not change to sql table and make it anchor. It would save you a lot of trouble.

    Nosh Mernacaj, Identity Management Specialist

    Thursday, June 18, 2015 11:29 PM
  • There is a way. A much easier way. All you need to do is deprovisiob old objet. New one will be created automatically. So on Metaverse you set deletion rule to say when ad ma is disconected, delete mv object. Then on sql ma you select delete connector under deprovisioning options.

    Nosh Mernacaj, Identity Management Specialist

    Hi Nosh,

    I have the deletion rules on the metaverse object set to delete the mvobject if the connector to adma is disconnected. On the SQLMA, I have "stage a delete on the next export run" option.

    Are you saying that I should disconnect the adma object from the metaverse object when the disinguishedName is different right on import flow extensions?


    • Edited by gtrivedi1980 Friday, June 19, 2015 9:48 AM correction.
    Friday, June 19, 2015 9:44 AM
  • But, why do you go this route anyways. Why dont you flow sAMAccountName or another attribute that does not change to sql table and make it anchor. It would save you a lot of trouble.

    Nosh Mernacaj, Identity Management Specialist

    sAMAccountName has the same problem. It can change. in our company we have firstname.lastname as samaccountname. Someone gets married and change their last name. So technically, their sAMAccountName will change and that will cause the same issue if I use sAMAccountName as anchor.

    Friday, June 19, 2015 9:45 AM
  • There is a way. A much easier way. All you need to do is deprovisiob old objet. New one will be created automatically. So on Metaverse you set deletion rule to say when ad ma is disconected, delete mv object. Then on sql ma you select delete connector under deprovisioning options.


    Nosh Mernacaj, Identity Management Specialist

    Hi Nosh,

    I have the deletion rules on the metaverse object set to delete the mvobject if the connector to adma is disconnected. On the SQLMA, I have "stage a delete on the next export run" option.

    Are you saying that I should disconnect the adma object from the metaverse object when the disinguishedName is different right on import flow extensions?



    If so, could you please share some code on how to do this? Thank
    Friday, June 19, 2015 9:57 AM
  • I am sorry, I don't have anything available at this time (At a client site), but this is not code. Simple configurations in FIM MV.  If you want to change the anchor, that means you need to change the schema of your SQL table, and then change the MA configuration.  Otherwise, this weekend I can send you something more clear.

    Nosh Mernacaj, Identity Management Specialist

    Friday, June 19, 2015 1:09 PM
  • Hi Nosh,

    I can change the anchor to something like ObjectGUID. I know that never changes, even if a user moves/ gets renamed in active directory. But setting the anchor as ObjectGUID is bad for people who would be using FIM to troubleshoot sync issues. They will see a bunch of GUIDs on and its not very intuitive. However, I'm not ruling out this option at all. But what I would like to do is the below. Please let me know if this can be done?

    I have two MAs.

    1. ADMA - used to import AD users and project/join to mv:person.

    2. SQLMA - used to export mv:Person to sql table. (anchor MemberDN which holds the distinguishedName of the corresponding user object from AD)

    let's say I have an account in ad (cn=oldname, ou=old ou, dc=domain). I import in FIM and export to SQLMA and a record gets written in SQL.

    Now what I would like to do is rename the account in AD to : cn=newname, ou=new ou, dc=domain

    Now when I import, I want fim to do the following within the same sync run.

    1. detect that distinguishedname has changed and delete or disconnect the mv:person object associated with the ADMA cs. also delete the sqlma cs object (I have set the object deletion rules on mv:person {delete mv:person object when the associated cs object is deleted from ADMA} and sqlma deprovision tab {stage a delete on the next export run}).

    2. I want to provision a new sqlma cs and flow the new distinguishedname to this sqlma cs.

    3. On the next export, SQLMA should create the new record and delete the old record from SQL table.

    Is it possible to do this?

    Friday, June 19, 2015 1:32 PM
  • Short answer, yes. This is what I mentioned on my earlier post. YES it is possible and on your case, the only way probably.

    All you have to do is find the way to remove old account. New one is created automatically - you need to do nothing extra since the provisioning code will take care of this.

    I would still stay aware from DN, though.  If anything I would use sAMAccountName (not sure it is something that changes for you, but still better). 


    Nosh Mernacaj, Identity Management Specialist

    Friday, June 19, 2015 1:50 PM
  • I would definitely be using the ObjectGUID as the SQL anchor, and not worry about the downside of the GUID being less pleasing on the eye as a DN.  The only alternative is the delete/add scenario you talk about, but it's not worth the effrort really.  In a troubleshooting scenario it's most likely you will start with either a Metaverse or SQL search - the CS search is also possible, for the minor inconvenience of looking up the guid in either the MV or AD.

    Bob Bradley (FIMBob @ TheFIMTeam.com) ... now using FIM Event Broker for just-in-time delivery of FIM 2010 policy via the sync engine, and continuous compliance for FIM

    • Proposed as answer by UNIFYBobMVP Thursday, August 13, 2015 11:33 AM
    Friday, June 19, 2015 2:07 PM
  • Short answer, yes. This is what I mentioned on my earlier post. YES it is possible and on your case, the only way probably.

    All you have to do is find the way to remove old account. New one is created automatically - you need to do nothing extra since the provisioning code will take care of this.

    I would still stay aware from DN, though.  If anything I would use sAMAccountName (not sure it is something that changes for you, but still better). 


    Nosh Mernacaj, Identity Management Specialist


    Thanks Nosh. Yeah sAMAccountName does change in our firm for a few people. So it could cause similar issues if I use it as an anchor on SQL.
    Friday, June 19, 2015 5:18 PM
  • I would definitely be using the ObjectGUID as the SQL anchor, and not worry about the downside of the GUID being less pleasing on the eye as a DN.  The only alternative is the delete/add scenario you talk about, but it's not worth the effrort really.  In a troubleshooting scenario it's most likely you will start with either a Metaverse or SQL search - the CS search is also possible, for the minor inconvenience of looking up the guid in either the MV or AD.

    Bob Bradley (FIMBob @ TheFIMTeam.com) ... now using FIM Event Broker for just-in-time delivery of FIM 2010 policy via the sync engine, and continuous compliance for FIM

    That's true. If I use ObjectGUID as anchor then I don't have to worry about distinguishedname renames. I can simply flow it through fim and it will update in SQL.

    Just out of curiosity, on the ADMA, is there any way to do a join on <dn> ? I don't see <dn> in the list of attributes available in AD CS that I can use for joining to metaverse object. Was thinking if its possible through code perhaps?

    Friday, June 19, 2015 5:21 PM
  • You can certainly do an advanced join on DN, but I highly advise you against as this may result on a bad join. 

    Nosh Mernacaj, Identity Management Specialist

    Friday, June 19, 2015 5:23 PM
  • You can certainly do an advanced join on DN, but I highly advise you against as this may result on a bad join. 

    Nosh Mernacaj, Identity Management Specialist

    Nosh, I was thinking if on ADMA I join on distinguishedName. Then after a full import/sync/export to sqlma, when I rename the account in AD (and distinguishedName will change). On the next import, FIM will detect a change and since we are joining on distingushedName, it will decide there is no mvobject:person with that distinguishedName so it will project a new mvobject:person and fire the provision code and create a new connector in sqlma. Then on export, sqlma will delete the old record in SQL and create this new record.

    Do you see this working? I haven't figured out how to join on distinguishedName on ADMA.

    Sunday, June 21, 2015 11:40 AM
  • No that is not the case. Join happens once. If there is already an object in mv that was joined prior, it remains joined no matter the changes are after. Only a change on anchor causes a new projection. In ADMA anchor is a guid that you cant change or controll. So joining is not going to help you.

    Nosh Mernacaj, Identity Management Specialist


    Sunday, June 21, 2015 4:45 PM