Skip to content

Синхронизация адресных книг Lotus Domino и Microsoft Exchange

05.06.2016

notes32b256pДля синхронизации адресных книг Microsoft Exchange двух организаций удобно использовать сценарий PowerShell, который разработал Carol Wapshere и опубликовал в своем блоге. Это замечательная, а главное бесплатная альтернатива использованию более тяжеловесных продуктов класса Identity Management. В процессе синхронизации сценарий создает в целевом лесу Active Directory объекты типа «контакт», соответствующие пользователям с почтовыми ящиками в исходном лесу. Благодаря созданным контактам становится возможным находить в адресной книге пользователей из другой организации и отправлять им сообщения.

Мне пришлось решать похожую задачу, однако почтовой системой — источником контактов для синхронизации был Lotus Domino. Соответственно, сценарий был существенно переработан, чтобы обеспечивалось подключение к LDAP-каталогу Lotus Domino. Как результат, пользователи Exchange получили возможность находить контакты Domino в собственной глобальной адресной книге Exchange.

Текст сценария GALSYNC.PS1 приведен в конце статьи. Его также можно загрузить по этой ссылке. Сделаю обзор переменных, которым необходимо присвоить значения применительно к вашим организациям. Для переменной $lotus_srv укажите доменное имя сервера Lotus Domino, к которому доступно подключение по протоколу LDAP. Обратите внимание, что в строке 64 сценария выполняется анонимное LDAP-подключение, без аутентификации. Если это недопустимо, измените строку подключения, как указано в статье «Using PowerShell to connect to Domino NAB«, т.е. примерно на такую :

$root = New-Object -TypeName System.DirectoryServices.DirectoryEntry($ldap_srv, "admin/notesadmin", "Password", [System.DirectoryServices.AuthenticationTypes]::None)

В переменной $targetDC укажите FQDN-имя любого домен-контроллера (не RODC) в вашей организации, в которой также развернут Exchange, либо можете просто указать имя домена. В качестве значения переменной $exch_fqdn подставьте полное имя сервера Exchange (с ролью CAS). Переменная $SMTPdomain должна содержать имя почтового домена вашей организации Exchange. Именно с таким доменным суффиксом создаваемым контактам будут назначаться локальные адреса электронной почты. Если вы не используете дополнительные имена почтовых доменов, тогда значение переменной $SMTPdomain должно совпадать с именем домена Active Directory.

А вот alias’ы и имена в локальных адресах электронной почты создаваемых контактов формируются из имен пользователей в каталоге Lotus Domino с прибавлением к ним префикса «c-«, например, c-username@yoursmtpdomain.com.

В переенной $targetOU укажите LDAP-путь к организационному подразделению, в котором будут создаваться контакты пользователей Lotus Domino. Если в этом OU будут находиться другие контакты, например, созданные вручную, то они могут быть удалены при синхронизации. Поэтому используйте данное OU только для целей синхронизации адресной книги Lotus. Доменный пользователь, UPN которого присваивается переменной $targetUser, должен обладать разрешениями создавать контакты в Exchange и изменять/удалять объекты типа «контакт» в Active Directory. Пароль пользователя сохраняется в защищенном виде в файле, путь к которому указывается в переменной $targetPWFile . Для создания файла выполните в командной строке PowerShell следующую команду:


read-host -assecurestring | convertfrom-securestring | out-file C:\scripts\domcred.txt

Текущая версия сценария имеет следующие ограничения, обусловленные рамками поставленной задачи.

  • В глобальную адресную книгу Exchange попадают только полные имена пользователей и адреса электронной почты в системе Lotus Domino, атрибуты Company и Description заполняются единообразно для всех синхронизируемых контактов. Другие атрибуты (например, должность, подразделение, номер телефона) не синхронизируются.
  • Заполнение атрибутов Company и Description происходит при втором проходе сценария, иными словами, у только что созданных контактов указанные атрибуты будут пустыми. Ограничение связано с тем, что командлет New-MailContact позволяет указать при создании лишь основные атрибуты. Остальные атрибуты приходится назначать в процессе модификации уже созданного объекта Active Directory, когда пройдут необходимые процессы репликации в AD.
  • В строке 81 сценария исключительно для целей тестирования введено ограничение числа импортируемых записей адресной книги Lotus и соответственно числа автоматически создаваемых контактов. В текущем варианте синхронизация происходит для записей с первой по десятую включительно. После того, как вы убедитесь, что сценарий работает должным образом, измените число 10 в указанной строке на какое-нибудь заведомо большое. 🙂

Несмотря на предпринятые меры по снижению негативных последствий неправильной работы сценария, вынужден предупредить, что тестирование не было проведено в достаточном объеме. Проверял и отлаживал его с Exchange 2010. Поэтому сценарий предлагается на ваше рассмотрение As Is, готов обсуждать, если что-то пойдет не так, но не нести за это  ответственность. Также не исключаю, что в дальнейшем буду вносить в сценарий изменения и дополнения, улучшающие его работу и функциональность.

 

### --- GALSYNC.PS1 ---
#
# Written by Carol Wapshere, Lotus adaptation by osr
#
# Manages mail enabled contacts in the target domain based on Lotus Domino users.
# - Contacts are created for new users.
# - Contacts are deleted if the source user no longer meets the filter requirements.
# - Contacts are updated with changed information.
#
# NOTES:
# - Requires RSAT roles and features installed. Ref http://blogs.technet.com/heyscriptingguy/archive/2010/01/25/hey-scripting-guy-january-25-2010.aspx
# - Attribute deletions are not replicated - only attribute adds and changes.
# - A user account is needed in a domain with permission to create contacts.
# - The password for this user account must be stored in secure files using the command:
# read-host -assecurestring | convertfrom-securestring | out-file C:\scripts\filename.txt

### --- GLOBAL DEFINITIONS ---

# Attributes, that will be added to all contacts
$description = "Lotus Organization Contact"
$company = "Another Company"

# FQDN of Lotus Domino Server
$lotus_srv = "lotussrv.otherdomain.com"

# FQDN of any writable domain controller in your organization, or simply your internal domain name
$targetDC = "yourdomain.com"

# FQDN of the Exchange server in your organization
$exch_fqdn = "yourexchange.yourdomain.com"

# Your SMTP domain name, it may coinside to the internal domain name or not
$SMTPDomain = "yoursmtpdomain.com"

# OU where contact objects will be placed
$targetOU = "OU=Contacts,OU=Other Organization,DC=yourdomain,DC=com"

# Domain user with the permission to manage contacts in Active Directory
$targetUser = "exchangeadm@yourdomain.com"

# Path to file that contains the encrypted password
$targetPWFile = "C:\scripts\domcred.txt"

### --- FUNCTION TO ADD, DELETE AND MODIFY CONTACTS IN TARGET DOMAIN BASED ON SOURCE USERS ---

if(@(get-module | where-object {$_.Name -eq "ActiveDirectory"} ).count -eq 0) {import-module ActiveDirectory}

$colContacts = @()
$colAddContact = @()
$colDelContact = @()
$colUpdContact = @()

$arrUserMail = @()
$arrContactMail = @()

write-host ""
write-host "Enumerating..."

### ENUMERATE USERS

$ldap_srv = "LDAP://" + $lotus_srv + ":389"
$root = New-Object -TypeName System.DirectoryServices.DirectoryEntry($ldap_srv, "", "", [System.DirectoryServices.AuthenticationTypes]::Anonymous)
$query = New-Object System.DirectoryServices.DirectorySearcher($root)
$query.Filter = "(objectClass=dominoperson)"
$Attribute = "cn", "uid", "mail"
$query.Searchscope = [System.DirectoryServices.SearchScope]::Subtree
$Attribute | foreach {[void]$query.PropertiesToLoad.Add($_)}
$query.SearchScope.all
$col = $query.findall()
# $ErrorActionPreference = "Stop"
$i = 1
$colusers=@{}
foreach ($lotus_usr in $col) {
If ((-Not [string]::IsNullOrEmpty($lotus_usr.properties.item("uid"))) -And (-Not ($lotus_usr.properties.item("mail") -match "[/%]"))) {
$AllMatches = [regex]::Matches($lotus_usr.properties.item("adspath"), "^LDAP://.+/CN=(.+)")
$AllMatches | Foreach-Object {$username = $_.groups[1].value}
$mailaddr = ($lotus_usr.properties.item("mail"))[0]
$username = [regex]::Replace($username,",O=.+$","")
If ($mailaddr) {
If ((-Not $colusers.ContainsKey($mailaddr)) -And ($i -ge 1) -And ($i -le 10)) {
$colusers[$mailaddr] = $username
Write-host $mailaddr
}
$i++
}
}
}

Write-host ""

if ($colUsers.Count -eq 0) {
write-host "No users found in Lotus Domino address book!"
break
}

### ENUMERATE CONTACTS

$password = get-content $targetPWFile | convertto-securestring
$targetCred = New-Object -Typename System.Management.Automation.PSCredential -Argumentlist $targetUser,$password

$ConUri = "http://" + $exch_fqdn + "/PowerShell/"
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $ConUri -Authentication Kerberos -Credential $targetCred
Import-PSSession $Session

$colContacts = Get-ADObject -Filter 'objectClass -eq "contact"' -searchbase $targetOU -Server $targetDC -Credential $targetCred -Properties targetAddress
# $colcontacts = get-mailcontact -OrganizationalUnit $targetOU

foreach ($contact in $colContacts)
{
$strAddress = $contact.targetAddress -replace "SMTP:",""
# $strAddress = $contact.ExternalEmailAddress -replace "SMTP:",""
$arrContactMail += $strAddress
}

### FIND CONTACTS TO ADD AND UPDATE

foreach ($user in [array]$colUsers.keys)
{
if ($arrContactMail -contains $user)
{
write-host "Contact found for " $user
$colUpdContact += $user
}
else
{
write-host "No contact found for " $user
$colAddContact += $user
}
}

### FIND CONTACTS TO DELETE

foreach ($address in $arrContactMail)
{
if ($address -And (-Not $colusers.containskey($address)))
{
$colDelContact += $address
write-host "Contact will be deleted for " $address
}
}

write-host ""
write-host "Updating ...."

### ADDS

foreach ($user in $colAddContact)
{
write-host "ADDING contact for " $user

$displayname = $colusers[$user]
$targetAddress = "SMTP:" + $user
$alias = "c-" + $user.split("@")[0]
$InAddr = $alias + "@" + $SMTPDomain

# $hashAttribs = @{'targetAddress' = $targetAddress}
# $hashAttribs.add('mailNickname', $alias)
# $hashAttribs.add('displayName', $displayname)

# New-ADObject -name $displayname -type contact -Path $targetOU -Description $description -server $targetDC -credential $targetCred -OtherAttributes $hashAttribs
$mailcontact = New-MailContact -Name $displayname -ExternalEmailAddress $user -Alias $alias -OrganizationalUnit $targetOU -PrimarySMTPAddress $InAddr
}

### UPDATES

foreach ($user in $colUpdContact)
{
write-host "VERIFYING contact for " $user

$displayname = $colusers[$user]
$strFilter = "targetAddress -eq ""SMTP:" + $user + """"
$colContacts = Get-ADObject -Filter $strFilter -searchbase $targetOU -server $targetDC -credential $targetCred -Properties *
foreach ($contact in $colContacts)
{
$upd = 0
$hashAttribs = @{}
If ($displayname -ne $contact.displayName) {
$upd++
write-host " Changing display name"
write-host " Before: " $contact.displayName
write-host " After: " $displayname
$hashAttribs.add("displayName", $displayname)
}
If ((-Not $contact.description) -Or ($contact.description -ne $description)) {
$upd++
write-host " Setting description"
$hashAttribs.add("description", $description)
}
If ((-Not $contact.company) -Or ($contact.company -ne $company)) {
$upd++
write-host " Setting company name"
$hashAttribs.add("company", $company)
}
If ($upd -gt 0) { Set-ADObject -identity $contact -server $targetDC -credential $targetCred -Replace $hashAttribs }

If ($displayname -ne $contact.name) {
write-host " Renaming the contact"
write-host " Before: " $contact.name
write-host " After: " $displayname
Rename-ADObject -identity $contact -Newname $displayname -server $targetDC -credential $targetCred
}

}
}

### DELETES

foreach ($contact in $colDelContact)
{
If ($contact) {
write-host "DELETING contact for " $contact
$strFilter = "targetAddress -eq ""SMTP:" + $contact + """"
Get-ADObject -Filter $strFilter -searchbase $targetOU -server $targetDC -credential $targetCred | Remove-ADObject -server $targetDC -credential $targetCred -Confirm:$false
}
}

Remove-PSSession $Session

 

Реклама
Добавить комментарий

Добавить комментарий

Заполните поля или щелкните по значку, чтобы оставить свой комментарий:

Логотип WordPress.com

Для комментария используется ваша учётная запись WordPress.com. Выход / Изменить )

Фотография Twitter

Для комментария используется ваша учётная запись Twitter. Выход / Изменить )

Фотография Facebook

Для комментария используется ваша учётная запись Facebook. Выход / Изменить )

Google+ photo

Для комментария используется ваша учётная запись Google+. Выход / Изменить )

Connecting to %s

%d такие блоггеры, как: