В предыдущих постах я описывал как связать разные службы каталогов при помощи ILM 2007. Здесь я объединю все заметки этой теме воедино.
Что из себя представляет ILM (Microsoft Identity Lifecycle Manager)? Состоит он из основных компонентов:
- Connected data source (подключаемые источники данных);
- Management Agents (агенты управления);
- Сonnector Spaces (пространства подключения);
- Metaverse (Метабаза).
и основные функции ILM:
- синхронизация каталогов;
- управление паролями и их синхронизация;
- управление группами;
- инициализация учетных записей;
- публикация сертификатов.
За более подробной информацией можно обраться к материалам на TechNet.
И так…, у нас есть Avtive Direcory (учетные записи пользователей для доступа к ресурсам Windows) – Sun One Direcory (доступ к почтовому серверу) – NetWare (доступ к ресурсам NetWare)
Не буду останавливаться на конфигурации агентов управления (MA),их можно посмотреть в предыдущих постах по этой теме. Приведу лишь пример исходных кодов DLL, которые мы будем использовать.
Metaverse Rules Extensions MVExtension.dll:
Imports Microsoft.MetadirectoryServicesImports SystemImports System.TextImports System.IOImports ActiveDs.ADS_USER_FLAGPublic Class MVExtensionObjectImplements IMVSynchronizationPublic Sub Initialize() Implements IMVSynchronization.Initialize' TODO: Add initialization code hereEnd SubPublic Sub Terminate() Implements IMVSynchronization.Terminate' TODO: Add termination code hereEnd SubPrivate Sub SetNovellPW(ByRef csentry As CSEntry, ByVal pw As String)' TODO: Setting an Initial Password in eDirectoryDim password() As Bytepassword = New System.Text.UTF8Encoding(False, False).GetBytes(pw)ReDim Preserve password(UBound(password) + 2)csentry("userPassword").Values.Add(password)End SubPrivate Sub SetSunDirPW(ByRef csentry As CSEntry, ByVal pw As String)' TODO: Setting an Initial Password in SUN Directory ServersDim password() As Bytepassword = New System.Text.UTF8Encoding(False, False).GetBytes(pw)csentry("userPassword").Values.Add(password)End SubPublic Sub Provision(ByVal mventry As MVEntry) Implements IMVSynchronization.ProvisionDim adMA As ConnectedMADim csentry As CSEntryDim dn As ReferenceValueDim ExceptionMessage As StringConst eDir_OU = "ou=Account,o=tree"Const eDir_MA = "MA_Novell"Const AD_MA = "MA_Active_Directory"Const ACTIVE_OU_AD = "OU=Branch,OU=Accounts,DC=dn,DC=local"Const INACTIVE_OU_AD = "OU=Disabled,OU=Accounts,DC=dn,DC=local"Const Sun_MA = "MA_Sun_Dir"Const SUN_OU = "ou=People,dc=dn,dc=local"Dim Connectors As IntegerDim Container As StringIf Not mventry("uid").IsPresent ThenExceptionMessage = "The attribute cn was unexpectedly not present on the metaverse object."Throw New UnexpectedDataException(ExceptionMessage)Exit SubEnd If' ======================================= '' eDirectory '' ======================================= 'adMA = mventry.ConnectedMAs(eDir_MA)Container = eDir_OUConnectors = adMA.Connectors.Countdn = adMA.EscapeDNComponent("cn=" + mventry("uid").Value).Concat(Container)'Throw New UnexpectedDataException("cn=" & mventry("cn").Value)If 0 = Connectors ThenIf ("cn=" + mventry("cn").Value + "," + ACTIVE_OU_AD).ToLower = mventry("DistinguishedName").Value.ToLower ThenSelect Case mventry.ObjectType.ToLower()'Case "group"' csentry = adMA.Connectors.StartNewConnector("groupOfNames")' csentry.DN = dn' csentry.CommitNewConnector()Case "person"csentry = adMA.Connectors.StartNewConnector("inetOrgPerson")csentry.DN = dncsentry("groupMembership").Values.Add("cn=Everyone,ou=Account,o=tree")csentry("securityEquals").Values.Add("cn=Everyone,ou=Account,o=tree")csentry("messageServer").Values.Add("cn=SR-NetWare,o=tree")SetNovellPW(csentry, "1Qaz2wsx")csentry.CommitNewConnector()End SelectEnd IfElseIf 1 = Connectors Thencsentry = adMA.Connectors.ByIndex(0)If csentry.DN.ToString.ToLower <> dn.ToString.ToLower Then'Throw New UnexpectedDataException("cn=" & mventry("cn").Value)' csentry.Deprovision()csentry.DN = dnEnd IfElseThrow New UnexpectedDataException("multiple connectors:" + Connectors.ToString)End If' ======================================= '' SUN ONE Directory '' ======================================= 'adMA = mventry.ConnectedMAs(Sun_MA)Connectors = adMA.Connectors.CountIf 0 = Connectors ThenDim objClass As ValueCollectionSelect Case mventry.ObjectType.ToLower()Case "person"'If mventry("mail").IsPresent ThenContainer = SUN_OUdn = adMA.EscapeDNComponent("uid=" + mventry("uid").Value).Concat(Container)csentry = adMA.Connectors.StartNewConnector("inetOrgPerson")csentry.DN = dnSetSunDirPW(csentry, "1Qaz2wsx")csentry.CommitNewConnector()objClass = Utils.ValueCollection(csentry.ObjectClass.ToStringArray())objClass.Add("mailRecipient")csentry.ObjectClass = objClass'End IfCase "group"If ("cn=" + mventry("cn").Value + ",OU=Groups,DC=dn,DC=local").ToLower = mventry("DistinguishedName").Value.ToLower ThenContainer = "ou=Groups," + SUN_OUdn = adMA.EscapeDNComponent("cn=" + mventry("uid").Value.ToLower).Concat(Container)csentry = adMA.Connectors.StartNewConnector("groupOfUniqueNames")csentry.DN = dncsentry.CommitNewConnector()objClass = Utils.ValueCollection(csentry.ObjectClass.ToStringArray())objClass.Add("mailRecipient")csentry.ObjectClass = objClassEnd IfEnd SelectElseIf 1 = Connectors ThenSelect Case mventry.ObjectType.ToLower()Case "group"Container = "ou=Groups," + SUN_OUdn = adMA.EscapeDNComponent("cn=" + mventry("uid").Value.ToLower).Concat(Container)Case "person"Container = SUN_OUdn = adMA.EscapeDNComponent("uid=" + mventry("uid").Value).Concat(Container)End Selectcsentry = adMA.Connectors.ByIndex(0)If csentry.DN.ToString.ToLower <> dn.ToString.ToLower Then'Throw New UnexpectedDataException("cn=" & mventry("cn").Value)' csentry.Deprovision()csentry.DN = dnEnd IfElseThrow New UnexpectedDataException("multiple connectors:" + Connectors.ToString)End If' ======================================= '' Active Directory '' ======================================= 'adMA = mventry.ConnectedMAs(AD_MA)Connectors = adMA.Connectors.CountSelect Case mventry.ObjectType.ToLower()Case "person"If mventry("msDS-UserAccountDisabled").IsPresent AndAlso mventry("msDS-UserAccountDisabled").BooleanValue ThenContainer = INACTIVE_OU_ADdn = adMA.EscapeDNComponent("cn=" + mventry("displayName").Value).Concat(Container)If adMA.Connectors.Count = 1 Then'Check if rename neededcsentry = adMA.Connectors.ByIndex(0)If csentry.DN.ToString.ToLower <> dn.ToString.ToLower Thencsentry.DN = dnEnd IfEnd IfEnd IfEnd SelectEnd SubPublic Function ShouldDeleteFromMV(ByVal csentry As CSEntry, ByVal mventry As MVEntry) As Boolean Implements IMVSynchronization.ShouldDeleteFromMVThrow New EntryPointNotImplementedException()End FunctionEnd Class
Metaverse Rules Extensions для MA Active Directory ADExtension.dll:
Imports Microsoft.MetadirectoryServicesImports SystemImports System.TextImports System.IOImports ActiveDs.ADS_USER_FLAGPublic Class MAExtensionObjectImplements IMASynchronizationPublic Sub Initialize() Implements IMASynchronization.Initialize' TODO: Add initialization code hereEnd SubPublic Sub Terminate() Implements IMASynchronization.Terminate' TODO: Add termination code hereEnd SubPublic Function ShouldProjectToMV(ByVal csentry As CSEntry, ByRef MVObjectType As String) As Boolean Implements IMASynchronization.ShouldProjectToMV' TODO: Remove this throw statement if you implement this methodThrow New EntryPointNotImplementedException()End FunctionPublic Function FilterForDisconnection(ByVal csentry As CSEntry) As Boolean Implements IMASynchronization.FilterForDisconnection' TODO: Add connector filter code hereThrow New EntryPointNotImplementedException()End FunctionPublic Sub MapAttributesForJoin(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByRef values As ValueCollection) Implements IMASynchronization.MapAttributesForJoin' TODO: Add join mapping code hereThrow New EntryPointNotImplementedException()End SubPublic 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' TODO: Add join resolution code hereThrow New EntryPointNotImplementedException()End FunctionPublic Sub MapAttributesForImport(ByVal FlowRuleName As String, ByVal csentry As CSEntry, ByVal mventry As MVEntry) Implements IMASynchronization.MapAttributesForImport' TODO: write your import attribute flow codeConst ADS_UF_ACCOUNTDISABLE As Integer = &H2 'Disable user accountConst ADS_UF_NORMAL_ACCOUNT As Integer = &H200 'Typical user accountSelect Case FlowRuleNameCase "nsAccountLock"If (csentry("userAccountControl").IntegerValue And ADS_UF_ACCOUNTDISABLE) = ADS_UF_ACCOUNTDISABLE Then'Account is disabledmventry("nsAccountLock").Value = "true"Else'Account is enabledmventry("nsAccountLock").Value = "false"End IfCase "UserAccountControl"mventry("msDS-UserAccountDisabled").BooleanValue = (csentry("userAccountControl").IntegerValue And ADS_UF_ACCOUNTDISABLE) = ADS_UF_ACCOUNTDISABLECase "Mail to Other Mailboxes"Dim csAttr As String = csentry("mail").Value.Replace("@domain1", "@domain2")mventry("otherMailbox").Value = csAttrEnd SelectEnd SubPublic Sub MapAttributesForExport(ByVal FlowRuleName As String, ByVal mventry As MVEntry, ByVal csentry As CSEntry) Implements IMASynchronization.MapAttributesForExportConst ADS_UF_ACCOUNTDISABLE As Integer = &H2Const ADS_UF_NORMAL_ACCOUNT As Integer = &H200Select Case FlowRuleNameCase "employeeStatus"Dim currentValue As LongIf csentry("userAccountControl").IsPresent ThencurrentValue = csentry("userAccountControl").IntegerValueElsecurrentValue = ADS_UF_NORMAL_ACCOUNTEnd IfSelect Case mventry("employeeStatus").ValueCase "active"csentry("userAccountControl").IntegerValue = (currentValue Or ADS_UF_NORMAL_ACCOUNT) _And (Not ADS_UF_ACCOUNTDISABLE)Case "inactive"csentry("userAccountControl").IntegerValue = currentValue _Or ADS_UF_ACCOUNTDISABLEEnd SelectEnd Select' TODO: Add export attribute flow code here'Throw New EntryPointNotImplementedException()End SubPublic Function Deprovision(ByVal csentry As CSEntry) As DeprovisionAction Implements IMASynchronization.DeprovisionThrow New EntryPointNotImplementedException()End FunctionEnd Class
Теперь у нас синхронизируются 3-ри службы каталогов…
Комментариев нет:
Отправить комментарий