Code placement
Hi all, I've written a piece of code to read a XML containing some parameters. I need to access these parameters in every management agent rules extension and every configured flow rule for every attribute in sync. In other words, I need to access these parameters everytime I synchronize attributes CS->MV and MV->CS. Reading from the XML file everytime a flow rule gets hit would make the rules extension very slow since every attribute in sync is configured as a advanced flow for import and export. Where can I place the code that reads from the XML file to keep the parameter list in the memory and be able to access the parameters from every management agent rules extension without loading the XML file every time. Thank you for your help in advance Chris
September 12th, 2011 3:55am

You should create a class that reads the configuration and is accessible through a instance of this class (public static instance). This is also called a singleton patern public class Singleton { // Thread-safe solution to make only a single instance private static Singleton _instance = new Singleton (); // Private constructor to prevent others to make other instances private Singleton () { } // Through a public property you can access the configuration public static Singleton Instance { get { return _instance; } } } You than can reference this class (if you put it in a seperate project/dll) and call Singleton.Instance.[property] Need realtime FIM synchronization? check out the new http://www.traxionsolutions.com/imsequencer that supports FIM 2010 and Omada Identity Manager real time synchronization!
Free Windows Admin Tool Kit Click here and download it now
September 12th, 2011 4:01am

You'll want to put the code in the Initialize method of your MA and MV extensions. I've seen both a unqiue config file per MA and provisioning - or - a single config file that is read by a common configuration class with each MA calling a 'ReadConfig' method on the master configuration class. In either case, you'll read the config in the Initialize section.. so.. every flow rule is an advanced flow (i.e. no direct flows) ? I don't think i've seen that except in some very unusual scenarios.Frank C. Drewes III - Consultant: Certified Security Solutions - My blog: http://www.css-security.com/author/fdrewes
September 12th, 2011 4:27am

Using a singleton patern you don't have to initialize this class in the MA initialization or MV extensions, whenever you call the public instance the initializing will be done once if not done before. You can read your config in the constructor in the above code example. Need realtime FIM synchronization? check out the new http://www.traxionsolutions.com/imsequencer that supports FIM 2010 and Omada Identity Manager real time synchronization!
Free Windows Admin Tool Kit Click here and download it now
September 12th, 2011 4:52am

I'm using FIM in an Active Directory migration project. I can only use the FIM synchronization service without the portal because of the license costs. I need to be able to control the attribute flow for every object depending on the object migration state. Migration state in this terms means the object is not migrated, in migration, allready migrated. e.g. - a user is not migrated: synchronize the sn from old to new active directory - a user is in migration: do not synchronize anything - a user is allready migrated: synchronize the sn from new to old active directory Since not all user objects can be migrated at the same time, I need to be able to control the attribute flow for every single object and every single attribute. Thank you for your help. I'll try to use the singleton pattern... I'll use a single configuration file for the MA and MV extensions.
September 12th, 2011 4:58am

Hi Christian, You can also use the store the parameters in the configuration settings section of the "C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Bin\miiserver.exe.config" file which runs under the process context of the MIIServer service account and the configurations are accesible from any MA or MV code. You can then use the Configuration Manager class to access the information without having to write a simpleton class or initialization code. as per the sample file and code below: Sample File <?xml version="1.0" encoding="UTF-16"?> <configuration> <configSections> <section name="resourceManagementClient" type="Microsoft.ResourceManagement.WebServices.Client.ResourceManagementClientSection, Microsoft.ResourceManagement"/> </configSections> <startup> <requiredRuntime version="v2.0.50727"></requiredRuntime> <supportedRuntime version="v2.0.50727"></supportedRuntime> </startup> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.MetadirectoryServicesEx" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="3.3.0.0" newVersion="4.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> <appSettings> <!-- OU Configuration--> <add key="employeesOU" value="OU=Users,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="adminaccountsOU" value="OU=Admin Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="serviceaccountsOU" value="OU=Service Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="resourceaccountsOU" value="OU=Resources Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com" /> <add key="disabledusersOU" value="OU=Disabled Users,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="contactsOU" value="OU=Contacts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="groupsOU" value="OU=User Groups,OU=CORE,DC=Test,DC=TestDom,DC=com"/> <!-- MA Name Configurtion --> <add key="ADMA" value="Active Directory - Users"/> <add key="SSPMA" value="Self-Service Provisioning"/> <add key="FPMA" value="FIM Service"/> <add key="ProvisionfromDYN" value="true" /> <add key="ProvisionfromSSP" value="false" /> <add key="ProvisionfromFP" value="true" /> <!-- Suffix Configuration --> <add key="DomainSuffix" value="@Test.TestDom.com"/> <add key="SMTPSuffix" value="@za.TestDom.com"/> <!-- InitialPassword Configuration--> <add key="UseCustomPassword" value="true"/> <!-- General Configuration items --> <add key="defaultManagerEmail" value="ZAFIMMAIL.Service@za.TestDom.com"/> <add key="defaultManagerdn" value="CN=Service\, ZAFIMMAIL,OU=Service Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="graceDays" value="0"/> <add key="logonMonths" value="6"/> <!-- Exchange messaging for email notifications configuration --> <add key="SharepointMailboxAddress" value="NewAccountsCreated@za.TestDom.com"/> <add key="HelpDeskAddress" value="TestDom@bcx.co.za"/> <add key="MailNotificationFromAddress" value="zafimmail.service@za.TestDom.com" /> <add key="MailNotificationCCMailbox" value="" /> <!-- old value outlook.Test.TestDom.com"/>--> <add key="UTCTimeFormat" value="yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000'" /> </appSettings> </configuration> Sample Code Imports Microsoft.MetadirectoryServices Imports Microsoft.MetadirectoryServices.Logging Imports System.Xml Imports System.Configuration Imports System.Exception Imports CustomUtils.Constants Imports CustomUtils.SendMail Public Class MAExtensionObject Implements IMASynchronization 'Global declarations Public ADMAName As String = ConfigurationManager.AppSettings("ADMA").ToString Public logonMonths As Integer = Integer.Parse(ConfigurationManager.AppSettings("logonMonths").ToString) Dim homeMDB As String = ConfigurationManager.AppSettings("homeMDBPath") Dim msExchHomeServerName As String = ConfigurationManager.AppSettings("homeServer") Public Sub Initialize() Implements IMASynchronization.Initialize ' TODO: Add initialize code here End Sub Public Sub Terminate() Implements IMASynchronization.Terminate ' TODO: Add termination code here End Sub Public Function ShouldProjectToMV(ByVal csentry As CSEntry, ByRef MVObjectType As String) As Boolean Implements IMASynchronization.ShouldProjectToMV ' TODO: Remove this throw statement if you implement this method Throw New EntryPointNotImplementedException() End Function Public Function FilterForDisconnection(ByVal csentry As CSEntry) As Boolean Implements IMASynchronization.FilterForDisconnection ' TODO: Add connector filter code here Throw New EntryPointNotImplementedException() End Function ''' <summary> ''' This subroutine function is used to map attribute values for the joining of AD accounts to metaverse objects ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="csentry"></param> ''' <param name="values"></param> ''' <remarks></remarks> Public Sub MapAttributesForJoin(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByRef values As ValueCollection) Implements IMASynchronization.MapAttributesForJoin Dim zeroChar As Char = CType("0", Char) 'Defines the character to use later in trimming the employee ID Select Case FlowRuleName ' Process the Rules Extension Case "cd.user#1:employeeID,extensionAttribute6->SSOPerson:employeeID" 'Ensure that only SSOPerson with employeeID starting with C If csentry("employeeID").IsPresent AndAlso csentry("employeeID").Value.ToLower.StartsWith("c") Then values.Add(csentry("employeeID").Value) End If 'Ensure that only SSOPerson with extensionAttribute6 starting with C If csentry("extensionAttribute6").IsPresent AndAlso csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then values.Add(csentry("extensionAttribute6").Value) End If 'Case "cd.user#2:employeeID,extensionAttribute6->SSOPerson:extensionAttribute6" ' 'Ensure that only SSOPerson with employeeID starting with C ' If csentry("employeeID").IsPresent AndAlso csentry("employeeID").Value.ToLower.StartsWith("c") Then ' values.Add(csentry("employeeID").Value) ' End If ' 'Ensure that only SSOPerson with extensionAttribute6 starting with C ' If csentry("extensionAttribute6").IsPresent AndAlso csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then ' values.Add(csentry("extensionAttribute6").Value) ' End If ' This case adds values to the employeeID in a trimmed & non trimmed state if the username does not start with admin Case "cd.user#1:employeeID,extensionAttribute6->person:employeeID" If csentry("employeeID").IsPresent AndAlso Not csentry("employeeID").Value.ToLower.StartsWith("c") Then Dim employeeID As String = csentry("employeeID").Value.TrimStart(New Char() {zeroChar}) values.Add(csentry("employeeID").Value) values.Add(employeeID) End If If csentry("extensionAttribute6").IsPresent AndAlso Not csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then Dim employeeID As String = csentry("extensionAttribute6").Value.TrimStart(New Char() {zeroChar}) values.Add(csentry("extensionAttribute6").Value) values.Add(employeeID) End If ' ' This case adds values to the extensionAttribute6 in a trimmed & non trimmed state if the username does not start with admin 'Case "cd.user#2:employeeID,extensionAttribute6->person:extensionAttribute6" ' If csentry("employeeID").IsPresent AndAlso Not csentry("employeeID").Value.ToLower.StartsWith("c") Then ' Dim employeeID As String = csentry("employeeID").Value.TrimStart(New Char() {zeroChar}) ' values.Add(csentry("employeeID").Value) ' values.Add(employeeID) ' End If ' If csentry("extensionAttribute6").IsPresent AndAlso Not csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then ' Dim employeeID As String = csentry("extensionAttribute6").Value.TrimStart(New Char() {zeroChar}) ' values.Add(csentry("extensionAttribute6").Value) ' values.Add(employeeID) ' End If Case Else Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' The function resolves possible duplicate joining objects ''' </summary> ''' <param name="joinCriteriaName"></param> ''' <param name="csentry"></param> ''' <param name="rgmventry"></param> ''' <param name="imventry"></param> ''' <param name="MVObjectType"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function ResolveJoinSearch(ByVal joinCriteriaName As String, ByVal csentry As CSEntry, ByVal rgmventry() As MVEntry, ByRef imventry As Integer, ByRef MVObjectType As String) As Boolean Implements IMASynchronization.ResolveJoinSearch Select Case joinCriteriaName ' First tries to join in a standard way if 1 connector exists, but if more than one exists, ' try to connect the one that is not in the disabled OU first. Case "cd.user#1" For Each mventry As MVEntry In rgmventry Dim ADMA As ConnectedMA = mventry.ConnectedMAs(ADMAName) If ADMA.Connectors.Count = 1 Then ' Only one connector, no resolution is needed ResolveJoinSearch = True imventry = 0 Exit Function ElseIf ADMA.Connectors.Count > 1 Then ' More than one connector, try to add the one not in the disabled OU first If Not ADMA.Connectors.ByIndex(0).DN.ToString.Contains("Disabled") = True Then ResolveJoinSearch = True imventry = 0 Exit Function End If End If Next ' Try adding the account by matching the trimmed "extensionAttribute" to the "employeeID" if the first and ' last names also match (to avoid incorrect objects joining with totally different names and surnames Case "cd.user#3" ResolveJoinSearch = False imventry = -1 If csentry("extensionAttribute6").IsPresent Then Dim zeroChar As Char = CType("0", Char) Dim csextensionAttribute6 As String = csentry("extensionAttribute6").Value.ToString.TrimStart(New Char() {zeroChar}) Dim index As Int32 = 0 For Each mventry As MVEntry In rgmventry If mventry("employeeID").IsPresent AndAlso _ mventry("employeeID").Value = csextensionAttribute6 Then If (mventry("givenName").Value = csentry("givenName").Value) AndAlso _ (mventry("sn").Value = csentry("sn").Value) Then ResolveJoinSearch = True imventry = index Exit Function End If End If index = index + 1 Next End If Case Else Throw New EntryPointNotImplementedException() End Select End Function ''' <summary> ''' This subroutine function maps the CS attributes to MV attributes for import into the metaverse ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="csentry"></param> ''' <param name="mventry"></param> ''' <remarks></remarks> Public Sub MapAttributesForImport(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByVal mventry As MVEntry) Implements IMASynchronization.MapAttributesForImport ' TODO: write your import attribute flow code Select Case FlowRuleName Case "IAFemployeeStartDate" If Not mventry("employeeStartDate").IsPresent Then Dim startdate As DateTime = Date.FromFileTimeUtc(Long.Parse(csentry("accountExpires").Value.ToString)) If mventry("contractDuration").IsPresent Then startdate = startdate.AddMonths(-Integer.Parse(mventry("contractDuration").Value.ToString)) Else startdate = startdate.AddMonths(-2) End If mventry("employeeStartDate").Value = startdate.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.000") End If Case Else ' TODO: remove the following statement and add your default script here Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' Maps attributes from a metaverse entry to a connector space entry during export operations. ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="mventry"></param> ''' <param name="csentry"></param> ''' <remarks></remarks> Public Sub MapAttributesForExport(ByVal FlowRuleName As String, ByVal mventry As MVEntry, ByVal csentry As CSEntry) Implements IMASynchronization.MapAttributesForExport ' TODO: Add export attribute flow code here Select Case FlowRuleName Case "EAFhomeMDB" Exit Select If Not csentry("msExchHomeServerName").IsPresent Then Dim randomnumber As New Random() Dim MDBDatabase As String = "CN=MDB0" & randomnumber.Next(1, 6).ToString csentry("homeMDB").Value = MDBDatabase & "," & homeMDB ' Set the homeMDB value End If Case Else ' TODO: remove the following statement and add your default script here Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' This function performs set actions to an AD object prior to disconnecting it from the Metaverse. ''' </summary> ''' <param name="csentry"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function Deprovision(ByVal csentry As CSEntry) As DeprovisionAction Implements IMASynchronization.Deprovision Deprovision = DeprovisionAction.Disconnect 'set the initial value as disconnect Select Case csentry.ObjectType Case "user" ' Disable the user account in the AD connector space. Dim currentValue As Long Dim disabledValue As Long If csentry("userAccountControl").IsPresent Then currentValue = csentry("userAccountControl").IntegerValue Select Case currentValue Case UF_NORMAL_ACCOUNT, _ UF_NORMAL_ACCOUNT + UF_DONT_EXPIRE_PASSWD, _ UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD, _ UF_NORMAL_ACCOUNT + UF_DONT_EXPIRE_PASSWD + UF_PASSWD_NOTREQD disabledValue = currentValue + UF_ACCOUNTDISABLE Case Else disabledValue = currentValue End Select Else disabledValue = UF_NORMAL_ACCOUNT End If csentry("userAccountControl").IntegerValue = disabledValue ' Hide the user from the GAL addresslists Try csentry("msExchHideFromAddressLists").BooleanValue = True Catch ex As Exception End Try ' Move the disabled user account to another container. Dim disabledContainer As String = ConfigurationManager.AppSettings("disabledusersOU").ToString Dim rdn As String = "CN=" & csentry("cn").Value Dim dn As ReferenceValue = csentry.MA.EscapeDNComponent(rdn).Concat(disabledContainer) Try csentry.DN = dn Catch ex As Exception Throw ex End Try Case "contact", "group" ' Delete the connector space object for a contact or group Deprovision = DeprovisionAction.Delete Case Else Throw New EntryPointNotImplementedException End Select End Function End Class Regards Jacques
Free Windows Admin Tool Kit Click here and download it now
September 12th, 2011 8:49am

Hi Christian, You can also use the store the parameters in the configuration settings section of the "C:\Program Files\Microsoft Forefront Identity Manager\2010\Synchronization Service\Bin\miiserver.exe.config" file which runs under the process context of the MIIServer service account and the configurations are accesible from any MA or MV code. You can then use the Configuration Manager class to access the information without having to write a simpleton class or initialization code. as per the sample file and code below: Sample File <?xml version="1.0" encoding="UTF-16"?> <configuration> <configSections> <section name="resourceManagementClient" type="Microsoft.ResourceManagement.WebServices.Client.ResourceManagementClientSection, Microsoft.ResourceManagement"/> </configSections> <startup> <requiredRuntime version="v2.0.50727"></requiredRuntime> <supportedRuntime version="v2.0.50727"></supportedRuntime> </startup> <runtime> <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1"> <dependentAssembly> <assemblyIdentity name="Microsoft.MetadirectoryServicesEx" publicKeyToken="31bf3856ad364e35" /> <bindingRedirect oldVersion="3.3.0.0" newVersion="4.0.0.0" /> </dependentAssembly> </assemblyBinding> </runtime> <appSettings> <!-- OU Configuration--> <add key="employeesOU" value="OU=Users,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="adminaccountsOU" value="OU=Admin Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="serviceaccountsOU" value="OU=Service Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="resourceaccountsOU" value="OU=Resources Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com" /> <add key="disabledusersOU" value="OU=Disabled Users,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="contactsOU" value="OU=Contacts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="groupsOU" value="OU=User Groups,OU=CORE,DC=Test,DC=TestDom,DC=com"/> <!-- MA Name Configurtion --> <add key="ADMA" value="Active Directory - Users"/> <add key="SSPMA" value="Self-Service Provisioning"/> <add key="FPMA" value="FIM Service"/> <add key="ProvisionfromDYN" value="true" /> <add key="ProvisionfromSSP" value="false" /> <add key="ProvisionfromFP" value="true" /> <!-- Suffix Configuration --> <add key="DomainSuffix" value="@Test.TestDom.com"/> <add key="SMTPSuffix" value="@za.TestDom.com"/> <!-- InitialPassword Configuration--> <add key="UseCustomPassword" value="true"/> <!-- General Configuration items --> <add key="defaultManagerEmail" value="ZAFIMMAIL.Service@za.TestDom.com"/> <add key="defaultManagerdn" value="CN=Service\, ZAFIMMAIL,OU=Service Accounts,OU=TestDom,DC=Test,DC=TestDom,DC=com"/> <add key="graceDays" value="0"/> <add key="logonMonths" value="6"/> <!-- Exchange messaging for email notifications configuration --> <add key="SharepointMailboxAddress" value="NewAccountsCreated@za.TestDom.com"/> <add key="HelpDeskAddress" value="TestDom@bcx.co.za"/> <add key="MailNotificationFromAddress" value="zafimmail.service@za.TestDom.com" /> <add key="MailNotificationCCMailbox" value="" /> <!-- old value outlook.Test.TestDom.com"/>--> <add key="UTCTimeFormat" value="yyyy'-'MM'-'dd'T'HH':'mm':'ss'.000'" /> </appSettings> </configuration> Sample Code Imports Microsoft.MetadirectoryServices Imports Microsoft.MetadirectoryServices.Logging Imports System.Xml Imports System.Configuration Imports System.Exception Imports CustomUtils.Constants Imports CustomUtils.SendMail Public Class MAExtensionObject Implements IMASynchronization 'Global declarations Public ADMAName As String = ConfigurationManager.AppSettings("ADMA").ToString Public logonMonths As Integer = Integer.Parse(ConfigurationManager.AppSettings("logonMonths").ToString) Dim homeMDB As String = ConfigurationManager.AppSettings("homeMDBPath") Dim msExchHomeServerName As String = ConfigurationManager.AppSettings("homeServer") Public Sub Initialize() Implements IMASynchronization.Initialize ' TODO: Add initialize code here End Sub Public Sub Terminate() Implements IMASynchronization.Terminate ' TODO: Add termination code here End Sub Public Function ShouldProjectToMV(ByVal csentry As CSEntry, ByRef MVObjectType As String) As Boolean Implements IMASynchronization.ShouldProjectToMV ' TODO: Remove this throw statement if you implement this method Throw New EntryPointNotImplementedException() End Function Public Function FilterForDisconnection(ByVal csentry As CSEntry) As Boolean Implements IMASynchronization.FilterForDisconnection ' TODO: Add connector filter code here Throw New EntryPointNotImplementedException() End Function ''' <summary> ''' This subroutine function is used to map attribute values for the joining of AD accounts to metaverse objects ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="csentry"></param> ''' <param name="values"></param> ''' <remarks></remarks> Public Sub MapAttributesForJoin(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByRef values As ValueCollection) Implements IMASynchronization.MapAttributesForJoin Dim zeroChar As Char = CType("0", Char) 'Defines the character to use later in trimming the employee ID Select Case FlowRuleName ' Process the Rules Extension Case "cd.user#1:employeeID,extensionAttribute6->SSOPerson:employeeID" 'Ensure that only SSOPerson with employeeID starting with C If csentry("employeeID").IsPresent AndAlso csentry("employeeID").Value.ToLower.StartsWith("c") Then values.Add(csentry("employeeID").Value) End If 'Ensure that only SSOPerson with extensionAttribute6 starting with C If csentry("extensionAttribute6").IsPresent AndAlso csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then values.Add(csentry("extensionAttribute6").Value) End If 'Case "cd.user#2:employeeID,extensionAttribute6->SSOPerson:extensionAttribute6" ' 'Ensure that only SSOPerson with employeeID starting with C ' If csentry("employeeID").IsPresent AndAlso csentry("employeeID").Value.ToLower.StartsWith("c") Then ' values.Add(csentry("employeeID").Value) ' End If ' 'Ensure that only SSOPerson with extensionAttribute6 starting with C ' If csentry("extensionAttribute6").IsPresent AndAlso csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then ' values.Add(csentry("extensionAttribute6").Value) ' End If ' This case adds values to the employeeID in a trimmed & non trimmed state if the username does not start with admin Case "cd.user#1:employeeID,extensionAttribute6->person:employeeID" If csentry("employeeID").IsPresent AndAlso Not csentry("employeeID").Value.ToLower.StartsWith("c") Then Dim employeeID As String = csentry("employeeID").Value.TrimStart(New Char() {zeroChar}) values.Add(csentry("employeeID").Value) values.Add(employeeID) End If If csentry("extensionAttribute6").IsPresent AndAlso Not csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then Dim employeeID As String = csentry("extensionAttribute6").Value.TrimStart(New Char() {zeroChar}) values.Add(csentry("extensionAttribute6").Value) values.Add(employeeID) End If ' ' This case adds values to the extensionAttribute6 in a trimmed & non trimmed state if the username does not start with admin 'Case "cd.user#2:employeeID,extensionAttribute6->person:extensionAttribute6" ' If csentry("employeeID").IsPresent AndAlso Not csentry("employeeID").Value.ToLower.StartsWith("c") Then ' Dim employeeID As String = csentry("employeeID").Value.TrimStart(New Char() {zeroChar}) ' values.Add(csentry("employeeID").Value) ' values.Add(employeeID) ' End If ' If csentry("extensionAttribute6").IsPresent AndAlso Not csentry("extensionAttribute6").Value.ToLower.StartsWith("c") Then ' Dim employeeID As String = csentry("extensionAttribute6").Value.TrimStart(New Char() {zeroChar}) ' values.Add(csentry("extensionAttribute6").Value) ' values.Add(employeeID) ' End If Case Else Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' The function resolves possible duplicate joining objects ''' </summary> ''' <param name="joinCriteriaName"></param> ''' <param name="csentry"></param> ''' <param name="rgmventry"></param> ''' <param name="imventry"></param> ''' <param name="MVObjectType"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function ResolveJoinSearch(ByVal joinCriteriaName As String, ByVal csentry As CSEntry, ByVal rgmventry() As MVEntry, ByRef imventry As Integer, ByRef MVObjectType As String) As Boolean Implements IMASynchronization.ResolveJoinSearch Select Case joinCriteriaName ' First tries to join in a standard way if 1 connector exists, but if more than one exists, ' try to connect the one that is not in the disabled OU first. Case "cd.user#1" For Each mventry As MVEntry In rgmventry Dim ADMA As ConnectedMA = mventry.ConnectedMAs(ADMAName) If ADMA.Connectors.Count = 1 Then ' Only one connector, no resolution is needed ResolveJoinSearch = True imventry = 0 Exit Function ElseIf ADMA.Connectors.Count > 1 Then ' More than one connector, try to add the one not in the disabled OU first If Not ADMA.Connectors.ByIndex(0).DN.ToString.Contains("Disabled") = True Then ResolveJoinSearch = True imventry = 0 Exit Function End If End If Next ' Try adding the account by matching the trimmed "extensionAttribute" to the "employeeID" if the first and ' last names also match (to avoid incorrect objects joining with totally different names and surnames Case "cd.user#3" ResolveJoinSearch = False imventry = -1 If csentry("extensionAttribute6").IsPresent Then Dim zeroChar As Char = CType("0", Char) Dim csextensionAttribute6 As String = csentry("extensionAttribute6").Value.ToString.TrimStart(New Char() {zeroChar}) Dim index As Int32 = 0 For Each mventry As MVEntry In rgmventry If mventry("employeeID").IsPresent AndAlso _ mventry("employeeID").Value = csextensionAttribute6 Then If (mventry("givenName").Value = csentry("givenName").Value) AndAlso _ (mventry("sn").Value = csentry("sn").Value) Then ResolveJoinSearch = True imventry = index Exit Function End If End If index = index + 1 Next End If Case Else Throw New EntryPointNotImplementedException() End Select End Function ''' <summary> ''' This subroutine function maps the CS attributes to MV attributes for import into the metaverse ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="csentry"></param> ''' <param name="mventry"></param> ''' <remarks></remarks> Public Sub MapAttributesForImport(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByVal mventry As MVEntry) Implements IMASynchronization.MapAttributesForImport ' TODO: write your import attribute flow code Select Case FlowRuleName Case "IAFemployeeStartDate" If Not mventry("employeeStartDate").IsPresent Then Dim startdate As DateTime = Date.FromFileTimeUtc(Long.Parse(csentry("accountExpires").Value.ToString)) If mventry("contractDuration").IsPresent Then startdate = startdate.AddMonths(-Integer.Parse(mventry("contractDuration").Value.ToString)) Else startdate = startdate.AddMonths(-2) End If mventry("employeeStartDate").Value = startdate.ToString("yyyy'-'MM'-'dd'T'HH':'mm':'ss.000") End If Case Else ' TODO: remove the following statement and add your default script here Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' Maps attributes from a metaverse entry to a connector space entry during export operations. ''' </summary> ''' <param name="FlowRuleName"></param> ''' <param name="mventry"></param> ''' <param name="csentry"></param> ''' <remarks></remarks> Public Sub MapAttributesForExport(ByVal FlowRuleName As String, ByVal mventry As MVEntry, ByVal csentry As CSEntry) Implements IMASynchronization.MapAttributesForExport ' TODO: Add export attribute flow code here Select Case FlowRuleName Case "EAFhomeMDB" Exit Select If Not csentry("msExchHomeServerName").IsPresent Then Dim randomnumber As New Random() Dim MDBDatabase As String = "CN=MDB0" & randomnumber.Next(1, 6).ToString csentry("homeMDB").Value = MDBDatabase & "," & homeMDB ' Set the homeMDB value End If Case Else ' TODO: remove the following statement and add your default script here Throw New EntryPointNotImplementedException() End Select End Sub ''' <summary> ''' This function performs set actions to an AD object prior to disconnecting it from the Metaverse. ''' </summary> ''' <param name="csentry"></param> ''' <returns></returns> ''' <remarks></remarks> Public Function Deprovision(ByVal csentry As CSEntry) As DeprovisionAction Implements IMASynchronization.Deprovision Deprovision = DeprovisionAction.Disconnect 'set the initial value as disconnect Select Case csentry.ObjectType Case "user" ' Disable the user account in the AD connector space. Dim currentValue As Long Dim disabledValue As Long If csentry("userAccountControl").IsPresent Then currentValue = csentry("userAccountControl").IntegerValue Select Case currentValue Case UF_NORMAL_ACCOUNT, _ UF_NORMAL_ACCOUNT + UF_DONT_EXPIRE_PASSWD, _ UF_NORMAL_ACCOUNT + UF_PASSWD_NOTREQD, _ UF_NORMAL_ACCOUNT + UF_DONT_EXPIRE_PASSWD + UF_PASSWD_NOTREQD disabledValue = currentValue + UF_ACCOUNTDISABLE Case Else disabledValue = currentValue End Select Else disabledValue = UF_NORMAL_ACCOUNT End If csentry("userAccountControl").IntegerValue = disabledValue ' Hide the user from the GAL addresslists Try csentry("msExchHideFromAddressLists").BooleanValue = True Catch ex As Exception End Try ' Move the disabled user account to another container. Dim disabledContainer As String = ConfigurationManager.AppSettings("disabledusersOU").ToString Dim rdn As String = "CN=" & csentry("cn").Value Dim dn As ReferenceValue = csentry.MA.EscapeDNComponent(rdn).Concat(disabledContainer) Try csentry.DN = dn Catch ex As Exception Throw ex End Try Case "contact", "group" ' Delete the connector space object for a contact or group Deprovision = DeprovisionAction.Delete Case Else Throw New EntryPointNotImplementedException End Select End Function End Class Regards Jacques
September 12th, 2011 8:49am

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

Other recent topics Other recent topics