none
Skip Provisioning RRS feed

  • Question

  • Hi All,

    How can I skip provisioning objects to all Connector spaces when a Full Synch run one particular management Agent.

    In other words,I don't want the provision method to run when a full Synch is run from one particular management agent and let the provision method run while running Synch cycles on other Management Agents.

    I am not concerned about correctness of design as of one

    Friday, October 14, 2016 5:44 AM

All replies

  • srinivasyk - you did not specify your method of provisioning, so I'll address it from a classic MV provisioning code view as it offers fine level control. That being said, I do not believe the method of control you seek is available at a default code level. The SyncEngine provisioning is based on the existence of an object in the MV, regardless of what MA is executing a run cycle. Nor is there any visibility of the currently executing MA run profile information from within the IMVSynchronization.Provision() function.

    But it could be accomplished in an out-of-band type scenario where an XML file is updated as to which MA/Profile is executing. Therefore that info can be consumed by the provisioning process and logic controls executed accordingly. I've used this technique in the past to handle development object level or connector level control, but never integrated with per-MA run profiles. Not exactly elegant and riddled with the possibility of getting your XML control file out of sync with your run cycle steps.

    Out of curiosity, what are your requirements leading to this type of control? Maybe it can be addressed in some other fashion?

    Best regards

    Friday, October 14, 2016 10:10 PM
  • Hi Terry Thanks for the reply.Yes I am talking about classic MV provisioning. Scenario We are replacing the out of box AD MA to custom powershell MA to read data from AD efficiently.we need to have powershell MA to run Full Sync and out of box AD MA to run Delta sync and provisioning .We don't have time to convert provisioning logic to powershell MA..So when we run Full Sync on powershell MA the attribute values should flow to MV and provisioning logic shouldn't get executed.on out of box AD MA run provisioning and export rules should get executed Please advice
    Saturday, October 15, 2016 12:53 AM
  • Ok I understand a little more as to what you're working with, but ultimately I have to ask what is the difference between the PS ADMA and the stock ADMA and what it contributes to the MV? To expand on what I said originally, the MV does not (and should not) care where the data comes from. If so, there's the attribute level Precedence feature to aide. So when you say "convert provisioning login to PS MA", that's where you lose me. Typically the target destination in MV provisioning code is can be written out in one line of code as simple as:

    ConnectedMA TargetMA = mventry.ConnectedMAs["Some-MA-Name"];

    And from there the MV determines if there is a connector and provisions accordingly. So changing which MA is the actual provision-to-target can be as simple as changing one string. (FWIW, all the MA names are worth putting in an XML control file for this very reason...) Or heck, is some cases you can simply rename the PS ADMA to that of the original ADMA and name the original ADMA to something else. Just need to make sure there are no other cause and effects from this.

    Is there something else I'm missing? Is there some difference to the data that the PS ADMA contributes vs. the stock ADMA? Why should the ADMA be required to run a sync? IMHO, converting the provision code to the correct MA would be much easier, reliable, supportable than hacking together some other method as to which MA run cycle determines provisions the object. Feel free to post your provision code for a review.

    And please expand on what type of efficiency gains (or capabilities) you're achieving with the PSMA? I know of some fringe situations where there might be a case, but I welcome the opportunity to learn from your efforts too.





    • Edited by Terry Phillips Saturday, October 15, 2016 8:56 AM One more idea...
    Saturday, October 15, 2016 8:48 AM
  • PS MA reads the values from AD in a multithreaded fashion,with this the sync time for full sync which was taking 20 hours is now reduced to 1 hour..PS MA reads all the values from AD and puts into xml and xml is read and fed to connnector space using Schema,importbegin,Import PS scripts.To export values back to AD I need to convert all the dotnet provisioning code in stock MA to Powershell in the export,begin export script and this is time consuming.

    So the plan now is to import values from PS MA and provisiong and export rules to be processed via stock AD MA so that the existing provisioning code can be retained.I am trying to avoid the provisining code getting hit on full sync of PS MA.

    Basically I am having two MAs fo single target which is causing the trouble.I understand the ideal way would be to get rid of stock AD MA and replace it with PS MA.

    Sample PS MA:

    https://blog.kloud.com.au/2016/01/28/provisioning-users-for-lync-skype-for-business-with-fim-mim-using-the-granfeldt-powershell-management-agent/
    Saturday, October 15, 2016 11:44 AM
  • Ahh - that clears it up quite a bit. When I hear the term "Provisioning Code" I immediately think of MV extension code where the provisioning decision (or not) generally occurs. I'd like to correct your interpretation of the FIM/ECMA process, quote: "I need to convert all the dotnet provisioning code in stock MA to PowerShell" The Granfelt PSMA or any custom ECMA still utilizes all the same FIM functions in the CS Extension Rules (ie., Join, Project, Import Attrib Flows, Export Attrib Flows, Provision, Deprovision, etc) against the CS objects the MA represents. So if there are custom code for those functions currently in the stock ADMA, the same code could be utilized with the PSMA. Or even the same extension.dll if the data is represented the same attribute name & datatype at the CS level. The true purpose of an ECMA is to allow the developer the ability to get data in/out of the CS to some target data source utilizing whatever method available for that source. Yet still allow a common API for the FIM level work.

    Also if the MV object has all the correct data there's no reason it should not be able to provision to the legacy ADMA target connector, to be staged as an export in the target CS (along with any export data transformations and other CS code requirements). This should work regardless of which MA is syncing, if not there are design flaws that need to be addressed vs which MA is running.

    So are you seeing errors when the run cycles execute? If so, try to explain them specifically.

    Saturday, October 15, 2016 1:53 PM
  • My understanding is in PS MA I need to directly establish a connection to AD (set-aduser) and assign the values to AD attributes which needs to be provisioned to AD.I can have the dotnet provision code and attach it for PS MA as provision code is common accross all MA and I have the luxury of providing the extension dll even in PS MA but my doubt is how will assign flow the attribute values to AD and export

    For example if my stock AD MA has something like below ,I need to take each attribute and assign the values in AD using PS one by one.Is it not so?If NO,how can I achieve this in my Export code of PS MA.Also in PS MA how will I map attributes of AD to MV and export them to AD as I don't really interact directly AD and rather with xml file(created from AD)

    As of now ,when I create a object in AD and run PS MA the provisioning code gets executed to stock AD CS(MA) and creates new object in stock AD CS with the same DN.On export of stock MA obviously there is an error saying the object already exists.That is the reason I wanted to avoid running provisioning code on PS MA run.Hope this is clear now.

    Public Sub Provision(ByVal mventry As Microsoft.MetadirectoryServices.MVEntry)_ Implements IMVSynchronization.Provision ' First, the telephone system only takes person objects If mventry.ObjectType.Equals("person") Then ' Also, telephone MA should only receive employee objects If mventry("EmpType").Value.ToLower = "employee" Then Dim csentry As CSEntry Dim PhoneMA As ConnectedMA = mventry.ConnectedMAs("Phone MA") ' If there is no connector present, add a new telephone connector If TelephoneMA.Connectors.Count = 0 Then csentry = TelephoneMA.Connectors.StartNewConnector("person") csentry("EMPID").Values.Add(mventry("employeeID").Value) csentry.CommitNewConnector() ElseIf PhoneMA.Connectors.Count = 1 Then ' Nothing to do, connector already exists for this MV object Else Throw New UnexpectedDataException("Multiple connectors:" + _ PhoneMA.Connectors.Count.ToString) End If End If 'employees only End If 'person objects only End Sub

    Public Sub MapAttributesForExport(ByVal FlowRuleName As String, _ 
    ByVal mventry As Microsoft.MetadirectoryServices.MVEntry, _ 
    ByVal csentry As Microsoft.MetadirectoryServices.CSEntry) Implements _
    Microsoft.MetadirectoryServices.IMASynchronization.MapAttributesForExport
        Const UF_ACCOUNTDISABLE = &H2
        Const UF_NORMAL_ACCOUNT = &H200
        Select Case FlowRuleName
        Case "userAccountControl"
            Dim currentValue As Long
            If mventry("employeeStatus").IsPresent Then
                If csentry("userAccountControl").IsPresent Then
                   currentValue = csentry("userAccountControl").IntegerValue
                Else
                   currentValue = UF_NORMAL_ACCOUNT
                End If
                Select Case mventry("employeeStatus").Value.ToLower
                Case "active"
                    csentry("userAccountControl").IntegerValue = (currentValue Or _
                              UF_NORMAL_ACCOUNT)  And (Not UF_ACCOUNTDISABLE)
                Case Else
                    csentry("userAccountControl").IntegerValue = currentValue Or _
                              UF_ACCOUNTDISABLE
                End Select
            End If
        Case Else
          Throw New UnexpectedDataException("Unexpected export flow rule name:"
    & FlowRuleName)
        End Select
    End Sub
    


    Saturday, October 15, 2016 2:33 PM
  • First off - what are your connected data sources? I get the PS ADMA and classic ADMA, but is that it? Do you have some other source of user data such as an HR MA? How does a user object get started in the FIM system?

    To clarify some FIM terminology (and I apologize as I don't intend to sound condescending but I find it hard discuss FIM, especially when the wrong terms are used or not understood):
    Import/Export - moving data to/from the Connector Space (CS) and a connected data source for a given MA
    Synchronization/Sync - the process sync'ing the CS data and applying the follow rules (plus others):

    • Join - the function of joining a CS object to an existing MV object
    • Projection - create a new MV object from a CS object if there are (typically) no joins
    • Import/Export Attribute Flows (IAF/EAF) - direct or coded
    • Disconnect/Delete for what to do when a connect MA's MV object is deleted

    Provision - the action of creating a new object from an existing MV object to a connected application (AD/SQL/File, etc) through an MA, when an object does not exist in that MA.

    "My understanding is in PS MA I need to directly establish a connection to AD (set-aduser) and assign the values to AD attributes which needs to be provisioned to AD." - You are correct, other than "provisioned" should be sync'ed. Also, your PowerShell would call New-ADUser to "provision" a new AD object.

    "...providing the extension dll even in PS MA but my doubt is how will assign flow the attribute values to AD and export" - This is where you are mixing 2 different concepts into 1.

    Concept 1) The extension code for a MA has functions for such logic as for userAccountControl as you have posted above (an EAF), whereas you take a mventry value, do some magic with it and post the result to the CS. If that value is different that the current value FIM sees it as a change and marks the Object/Attribute as a pending export. 

    Concept 2) With an ECMA, you are responsible for taking that csentry change value and writing it to the target, as I take it you understand that to be the case as you stated in the first sentence. Just keep in mind, your PS code is not responsible to manipulating the mventry("employeestatus") value to a csentry("userAccountControl") value, that's done in the extension.dll. You PS code simply takes that userAccountControl value modified by the extension.dll from the csentry object and writes it to AD.

    The principals of the ECMA don't really intend for data transformations and logic to be in the actual import/export flows you write in powershell, only data transport and necessary datatype conversions such as datetime->string on import and string->datetime on export, etc.

    To summarize -  with stock ADMA, its:

    • Mventry<->MA.extension.dll<->csentry<->AD

    with PS MA it's:

    • Mventry<->MA.extension.dll<->csentry<->PowerShell<->AD

    Where as the stock ADMA does the reading writing to AD for you, an ECMA that responsibility is yours

    "Also in PS MA how will I map attributes of AD to MV and export them to AD as I don't really interact directly AD and rather with xml file(created from AD)" - With your PSMA, you still have to define what attributes are part of your schema, and the IAFs/EAFs per attribute, either as direct flows or extension ruled based. As Syncs are run, any calculated change will be staged as a pending export. Your responsibility is to consume those pending changes and write them to AD with your PS code.

    "As of now ,when I create a object in AD and run PS MA the provisioning code gets executed to stock AD CS(MA) and creates new object in stock AD CS with the same DN" - This is root of your issue and the design flaw that needs to be addressed. Example: In your code above the "TelephoneMA" looks at the connector count. If 0 create new connector (i.e., Provision new object to connected data source), if 1 do nothing. There should be something similar for your ADMA. To Note: with ldap sources, the "if == 1" is generally used to rename existing connected objects for moves, etc. Either the "count" test does not account for existing objects, or there is more than one place that your AD provisioning code exists and it not checking the proper MA for count.



    • Edited by Terry Phillips Saturday, October 15, 2016 6:24 PM apology...
    Saturday, October 15, 2016 6:09 PM
  • As of now ,when I create a object in AD and run PS MA the provisioning code gets executed to stock AD CS(MA) and creates new object in stock AD CS with the same DN" - This is root of your issue and the design flaw that needs to be addressed. Example: In your code above the "TelephoneMA" looks at the connector count. If 0 create new connector (i.e., Provision new object to connected data source), if 1 do nothing. There should be something similar for your ADMA. To Note: with ldap sources, the "if == 1" is generally used to rename existing connected objects for moves, etc. Either the "count" test does not account for existing objects, or there is more than one place that your AD provisioning code exists and it not checking the proper MA for count.

    This is my problem.

    ConnectedMA TargetMA = mventry.ConnectedMAs["ADMA"];

    If TargetMA.Connectors.count =0 Then  (This one returns zero when PS MA sync runs as the AD CS doesnt have a connector for the object already but PS MA has and tried to create new one.When that objects tries to get exported the sync error object already exists pops up.That is when I thought of ignoring the provisioning code when PS MA runs and just imports the values from AD)

    Please correct me if I am wrong.


    Sunday, October 16, 2016 9:53 AM
  • Can you please post the code for the MV extension and each MA extension, specifically the .provision methods?
    Sunday, October 16, 2016 11:40 AM
  • Its quite huge with various methods in different files.While I try to gather all the code,Shall I post the provisioning code of AD MA for your suggestion.


    New objects are provisioned as below
    --------------------------------
    MAName="ADMA"
    ConnectedMA ma = mventry.ConnectedMAs[MAName];
    CSEntry csentry = ma.Connectors.StartNewConnector("group");
    csentry.DN = ma.CreateDN(GetGroupDN(mventry));
    csentry.name='test';
    csentry.CommitNewConnector();

    If object already exists check
    ------------------------------
    ConnectedMA ma = mventry.ConnectedMAs["ADMA"];
    CSEntry csentry = ma.Connectors.ByIndex[0];
    csentry.DN="NEW-OU"


    My export of PS is like this as of now which is unused.

    foreach($CSEntry in $CSEntries) {            
        switch ($CSEntry.ObjectType) {            
            'group' {            
                switch ($CSEntry.ObjectModificationType) {            
                    'Update' {            
    //It needs to be updated with set-aduser and new-aduser for each object as you suggest if I have to replace the AD MA completely but I am not sure how do I go about it.
                            }            
                        }            
                    }            
                }            
            }            
        }            
    }            

    New-FIMPutExportEntriesResults

                                    
    Sunday, October 16, 2016 12:42 PM
  • srinivasyk - if you'd like you can email me the code directly at my "givenName (dot) sn at company (dot) com". And if you're available via Lync/Sfb/Skype/Messenger, it might be a more efficient form of communication to straighten this out...
    Sunday, October 16, 2016 2:22 PM
  • Sure Terry.will work on that and get back to you.
    Monday, October 17, 2016 4:03 AM