OT: FIM/MIM question

  • 156 Views
  • Last Post 01 September 2016
barkills posted this 08 August 2016

General approach question on FIM/MIM sync engine—I don’t actively work with this product often enough to have a great idea on what the best approach is.   I’m trying to improve a minor, but annoying problem we’ve had with our deployment that requires manual intervention a couple times a month. Basically, CS objects meet the criteria to be joined to MV at one point in time, but later they no longer meet that criteria. I’d like to disconnect those CS objects from the MV object when they no longer meet the join criteria (some latency OK).   I took a look at the recently updated PS module at https://fimpowershellmodule.codeplex.com/releases/view/103901 (nice work Brian Desmond). I think it is true that I can’t work directly with MV objects using the WMI namespace underlying that stuff. I might be able to work around that by coming at it from the CS space, but I don’t see any way to get a collection of all CS objects. So this seems like a dead end for my problem.   I pulled out our existing FIM extension code because I recalled better classes and methods available there. The IMASynchronization.FilterForDisconnection method (https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.metadirectoryservices.imasynchronizationmethods(v=vs.100).aspx) looks very promising, but the documentation about it is both sparse and has convoluted language that leaves me wondering if it really is what I want. There are also no examples, which makes it trial & error guesswork to find out. I also wonder about the impact of using this method on our overall sync run profile times.   Got any wisdom, examples or suggestions for me? Feel free to send me elsewhere. J   Brian  

Order By: Standard | Newest | Votes
ZJORZ posted this 01 September 2016

This is code for the object deletion rule




We were talking about the disconnection in the provisioning code at mv level and the connector filter at cs level



Met vriendelijke groet / Kind regards,


Jorge de Almeida Pinto



E-Mail:

JorgeDeAlmeidaPinto@xxxxxxxxxxxxxxxx



Tel.: +31-(0)6-26.26.62.80



(+++Sent from my mobile device +++)


(Apologies for any typos)

show

cduers posted this 01 September 2016

And here is one for filterForDisconnection

 

#region "FilterForDisconnection. This function is used to filter out special conditions

when multiple employee records exist"

             

bool IMASynchronization.FilterForDisconnection (CSEntry csentry)

              {

                    



                    

//

                    

// The rule is:

                    

//    Use the highest number employee record (emplrcd = 1 or 2)

                    

//      when employee class = 'E', except when employee status = 'T'

                    

// Therefore, we have two filter conditions when empl
rcd = '1' or '2'

                    

//    1. when class = 'E' and status = 'T'

                    

//    2. when class <> 'E'

                    

int rcdCount = Convert.ToInt32(csentry["emplrcd"].StringValue);

                    

if (rcdCount > 0)

                     {

                          

if ((csentry["emp
class"].IsPresent) && (csentry["empclass"].Value.ToUpper().Equals("E")))

                           {

                                 

if ((csentry["empl
status"].IsPresent) && (csentry["emplstatus"].Value.ToUpper().Equals("T")))

                                  {

                                        

// filter

                                        

return true;

                                  }

                           }

                          

else

                           {

                                 

// filter

                                 

return true;

                           }

                     }

                          



                    

// Non-filter

                    

return false;

                          



              }     

// end of bool IMASynchronization.FilterForDisconnection (CSEntry csentry)

              #endregion

 

 



Christopher Duers

XL Catlin,

Identity and Security

203-979-3914

chris.duers@xxxxxxxxxxxxxxxx

 



 



 

show

cduers posted this 01 September 2016

Here’s an example of the shouldDeleteFromMV usage

 

        #region "IMVSynchronization.ShouldDeleteFromMV (CSEntry csentry, MVEntry mventry)"

       

bool IMVSynchronization.ShouldDeleteFromMV(CSEntry csentry,

MVEntry mventry)

        {

           

//Logging.Log(" ... ShouldDeleteFromMV (" + mventry.ObjectID.ToString() + ")", true, 3);

           

Logging.Log(" ... ShouldDeleteFromMV ",

true, 3);

 

 

           

// This section provides the MV deletion logic.

           

// Primary functionality here is the deletion of the MV object and setting transaction property to

           

//    trigger the deprovisioning of the connected AD user object.

 

           

// The XL PSHR MA is the only management agent authoritative for [employee person] object deletion

           

//   so we need to limit the scope of the object deletion rule to just CS Entries deleted via this MA.

           

//   For example, if a user goes inactive and is thereby by deleted from the GroupPopulator CS when

           

//      a full or delta synch is run on that MA, this rule will fire without the MA name check below.

           

//      This wouldn't be the desired behavior.  With the name check, the two entries are deleted from

           

//      the GroupPopulator CS but not from the MV and its connected directories.

           

// The AD MA is the only management agent authoritative for [non-employee person] object

           

//   deletion so we need to limit the scope of the object deletion rule to just CS Entries deleted via

           

//   this MA.

           

if (csentry.MA.Name.Equals(xl
HRMAName))

           

// OK, the CS Entry was deleted from the HR data source - authoritative for employee persons

            {

               

Logging.Log("HR MA object delete (" + csentry["emplid"].Value +

"+" + csentry["empl
rcd"].Value +

").", true, 1);

               

if ((mventry["xlEDSDn"].IsPresent) || (mventry.ConnectedMAs[xlEDSMAName].Connectors.Count == 1))

                {

                   

Logging.Log(" ... EDS connector present; retaining MV object.",

true, 1);

                   

return false;  

// don't fire the object deletion logic

                }

               

else

                {

                   

Logging.Log(" ... Object deletion rule fired for [" + mventry["uid"].Value +

"]", true, 1);

                   

return true;  

// fire the object deletion logic

                }

            }

// end of if (csentry.MA.Name.Equals(xlHRMAName))

 

           

else if (csentry.MA.Name.Equals(xlADMAName))

            // OK, the CS Entry was deleted from the Non-Employee data source - authoritative for non-employee persons

            {

               

Logging.Log("AD MA object delete (" + csentry["sAMAccountName"].Value +

").", true, 1);

               

if ((mventry["xlDataSource"].IsPresent) && (mventry["xlDataSource"].Value.Equals("AD")))

 

               



                // OK, this is a consultant sourced from AD or a newer test ID

                {

                   

if ((mventry["xlEDSDn"].IsPresent) || (mventry.ConnectedMAs[xlEDSMAName].Connectors.Count == 1))

                    {

                       

Logging.Log(" ... EDS connector present; retaining MV object.",

true, 1);

                       

//return false;   // don't fire the object deletion logic

                       

return false;  

// don't fire the object deletion logic

                    }

                   

else

                    {

                       

Logging.Log(" ... Object deletion rule fired for [" + mventry["uid"].Value +

"]", true, 1);

                       

return true;  

// fire the object deletion logic

                    }

                }   

// end of if ( (mventry["xlPersonType"].Value.Equals("N")) && (mventry["xlDataSource"].Value.Equals("AD")) )

               

else

                {

                   

Logging.Log(" ... AD connector deleted; MV object retained for object",

true, 1);

                   

return false;  

// don't fire the object deletion logic

                }

            }

// end of else if (csentry.MA.Name.Equals(xlADMAName))

           



            else

            {

               

return false;    

// don't fire the object deletion logic

            }

 

        }    

// end of bool IMVSynchronization.ShouldDeleteFromMV (CSEntry csentry, MVEntry mventry)

        #endregion

 

 



Christopher Duers

XL Catlin,

Identity and Security

203-979-3914

chris.duers@xxxxxxxxxxxxxxxx

 



 



 

show

barkills posted this 29 August 2016

My apologies for the slow response on this—combination of vacation and busy times.

 

I didn’t understand the rule of thumb for where to add code to address this (because the word originate needs context to be understood and assumes the answer

is a single location & there was disagreement). If more detail helps, I’ve added that down below, but I don’t think this is a detail issue.

 

I’ve taken a look at the general description of both

-

IMASynchronization.FilterForDisconnection method (https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.metadirectoryservices.imasynchronization.filterfordisconnection(v=vs.100).aspx)

And

- IMVSyncronization.ShouldDeleteFromMV method (https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.metadirectoryservices.imvsynchronization.shoulddeletefrommv(v=vs.100).aspx)



 

The MV method (shouldDeleteFromMV) results in deleting a MV object. The MA method (filterForDisconnection) deletes a CS connector. The MV method isn’t what I

want, and the MA (CS) method (filterForDisconnection) is.

 

I still don’t have any example of code which calls this method … anyone have sample code that calls this method that they can share?



 

Brian

 

------------------

More detail on the problem I’ve trying to address:

 

There are two connector spaces: AD & OpenLDAP (via custom LDIF). Only the AD CS has any export flows.

 

The OpenLDAP CS has three object types of import:  uwNetIDObject, uwPerson, uwPrincipal.

 

MV objects are projected from the OpenLDAP based uwNetIDObject. Joins all happen via the uwNetID attribute, when there is a matching value on OpenLDAP uwPerson,

OpenLDAP uwPrincipal, or AD user.

 

The uwNetIDObject never has a uwNetID attribute value change. The others can all have their uwNetID attribute change.

 

Relevant to the problem I’m trying to fix, outside of these systems, there are two identity transactions happening that contribute to the problem:

-Merging separate identities which have just been discovered to be the same person (userA & userB merge into either userA or userB). Complicating this one is

that some of the data for userA and userB is tied to a third (and fourth) identity record behind the scenes, but I’ll try to avoid explaining those complexities.

-Cleaning up after help desk accidents when they do the wrong thing with a user rename (create new user, try to rename, oops!, delete new user, rename old to

new)

 

The usual state of objects when manual intervention is needed is:

OpenLDAP uwNetIDObject userA projected to MV object userA. OpenLDAP uwNetIDObject userB projected to MV object userB.



AD userA joined to userA MV object. AD userB joined to userB MV object.

OpenLDAP uwPerson or uwPrincipal userA object can’t join to userA MV object. OpenLDAP uwPerson or uwPrincipal userB object is joined to userA MV object.

 

The manual intervention is to disconnect OpenLDAP uwPerson or uwPrincipal userB object from userA MV object. A subsequent delta sync results in OpenLDAP uwPerson

or uwPrincipal userA object correctly joining to userA MV object, and OpenLDAP uwPerson or uwPrincipal userB object joining to userB MV object, if one exists.

 

show

bdesmond posted this 16 August 2016

I’d do it in provisioning code myself (knowing what I know from the thread anyway) but that’s just me.



 



Thanks,

Brian Desmond

 

w – 312.625.1438 | c – 312.731.3132



 

show

ZJORZ posted this 15 August 2016

Shouldn't it be the other way around?




If the data change originates from the cs use the connector filter

If the data change originates from the mv, due to some other cs, use the provisioning code



Met vriendelijke groet / Kind regards,


Jorge de Almeida Pinto



E-Mail:

JorgeDeAlmeidaPinto@xxxxxxxxxxxxxxxx



Tel.: +31-(0)6-26.26.62.80



(+++Sent from my mobile device +++)


(Apologies for any typos)

show

bdesmond posted this 15 August 2016

Does data change in your connector space that indicates this? If so, the correct place to do this is in your provisioning code (IMVExtension).

 

There’s another third party PS Module on Github for FIM Sync that exposes undocumented (and unsupported) APIs to do things you can do in the UI (like disconnect CS

objects), YMMV.

 



Thanks,

Brian Desmond

 

(w) 312.625.1438 | (c) 312.731.3132



 

show

ZJORZ posted this 11 August 2016

To connect/disconnect objects you can use either the connector filter at CS level or the disconnection method in the provisioning code at MV level. In both cases you need to be carefull due to the object deletion rule at MV level. Which one you use really depends on your logic and environment
Met vriendelijke groet / Kind regards,
Jorge de Almeida Pinto
E-Mail: JorgeDeAlmeidaPinto@xxxxxxxxxxxxxxxx
Tel.: +31-(0)6-26.26.62.80
(+++Sent from my mobile device +++)
(Apologies for any typos)

Close