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