пятница, 1 февраля 2013 г.

Автоматическое обновление сертификатов на Lync серверах

Развертывание Mediation\SBA серверов в представительствах может показаться не такой уж и плохой идеей, ровно до того момента, как приходит понимание, что для каждого сервера необходим персональный сертификат и их необходимо периодически обновлять.

Для покупных сертификатов у меня есть отдельная Excel табличка, которая генерирует csv, по которому скрипт на пару с дорогим мне поставщиком сертификатов отправляет уведомления при истечении срока действия сертификата, но обновлять сертификаты более чем на 10 серверах я не хочу.

Данная задача вполне может быть автоматизирована, хотя и не весьма тривиально.

Сделать сертификат просто обновляемым через autoenrollemnt политику нельзя - сертификат должен быть присвоен серверу в топологии Lync. Назначать (и запрашивать на CA) сертификат необходимо при помощи командлетов Lync, что удобно - 2 командлета и всё готово.

Первой попыткой решить данную проблему было запускать процесс обновления через Remoting - очень удобно, контролируемо, централизовано. К сожалению, сделать это не получилось, т.к. по неизвестным мне причинам сертификат не захотел назначать при запуске через Remoting. Чтобы обойти данное ограничение процесс был разбит на два этапа - периодическая генерация сертификата заданием на сервере и контроль за сроком действия сертификатов через Remoting. Без этапа контроля срока нет гарантии, что задание выполнится, сертификат не обновится или возникнет какая-нибудь другая проблема.

Задача на серверы создается групповой политикой через Preferences с фильтрацией по членству в группе Hosts.LyncMediation (Item level targetting), чтобы использовать одну групповую политику на всех серверах для всех офисов. Таким же методом на сервере создается файл со скриптом задания - выполнения скрипта с удаленной общей папки на мой взгляд стоит всячески избегать.

Я сразу генерирую сертификат по шаблону для SBA. Почему lync хочет включить туда имя Edge сервера я не знаю, но если просит и сертификат бесплатный, то можно и согласиться, а то вдруг что. Скрипт, занимающийся обновлением сертификатов на сервере выглядит так:

import-module lync
#центр сертификации
$ca="issuing.contoso\ISSUING"
#Наш почтовый сервер
$mailserver="192.168.0.8"

$fqdn=$env:computername
$date=get-date
$name=$fqdn+" "+$date.day+"."+$date.month+"."+$date.year

$cert=Request-CSCertificate -New -CA $ca -Type Default -Country RU -State "Moscow" -City "Moscow" -FriendlyName $name -KeySize 2048 -PrivateKeyExportable $true -Organization "Contoso LLC" -OU "IT" -Template "webserver" -DomainName "sip.contoso.com" 
if($cert) {
    Set-CSCertificate -Type Default -Thumbprint $cert.Thumbprint -Verbose -Confirm:$false 
} else {
    $msg="На сервере $fqdn не удалось обновить сертификат Lync"
    Send-MailMessage  -From admin@contoso.com -to admin@contoso.com -Subject "[Отчет] Обновление сертификатов Lync" -Body $msg -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8) -SmtpServer $mailserver   
}

Скрипт работает следующим образов: запрашиваем сертификат по шаблону, в дружественном имени проставляем дату запроса, при неудаче отправляем письмо.

Скрипт мониторинга берет список серверов для проверки (с сервисом mediation) из топологии Lync, эти серверы добавляются в группу Hosts.LyncMediation и по этой группе совершается обход. Это очень удобно, если сервер "случайно" забыли включить в соответствующую группу безопасности.

########################################################################
# Загрузить топологию Lync, заполнить группу hosts.lyncmediation
# серверами с ролью Mediation(SBA). Пройтись по данным серверам
#  и проверить актуальность сертификатов.

Import-Module activedirectory
import-module lync
$registrar_regex="^Registrar:(?([A-Za-z0-9.]*)"
$mediation_regex="^MediationServer:(?([A-Za-z0-9.]*)"
#это имя главного пула, на нем всё делается вручную, в частности заказываются покупные сертификаты
$main_fqdn="lyncpool01.contoso.com"
$mailserver="192.168.0.8"
$mail_from="admin@contoso.com"
$mail_to="admin@contoso.com"
#отправить письмо, если сертификат истекает через X дней
$days_warn=30

$servers=@()
$servers_warn=@{}
$now=get-date

#обойти топологию, найти все серверы с ролью mediation (SBA будут включены)
$pool=get-cspool
foreach($p in $pool) {
    $fqdn=$p.fqdn
    #skip main pool
    if ($fqdn -eq $main_fqdn) {continue}
    
    foreach ($i in $p.services) {
        if ($i -match $mediation_regex) {
            $servers+=$fqdn
        }
    }
}

$members_lyncmediation=(Get-ADGroup hosts.lyncmediation -Properties members).members

foreach ($fqdn in $servers) {
    #добавляем сервер в группу hosts.lyncmediation
    $comp=Get-ADComputer -Filter {dnshostname -eq $fqdn}
    if($comp) {
        #проверяем сервер на членство в группе, чтобы лишний раз не добавлять его в группу - генерируется ошибка
        if($members_lyncmediation -notcontains $comp.DistinguishedName) {
            Add-ADGroupMember "hosts.lyncmediation" -members $comp -erroraction "silentlycontinue"
        }
    }
    
    #подключаемся к компьютеру
    $session=New-PSSession -Computername $fqdn -erroraction "silentlycontinue"
    if (!$session) {
        $failed_hosts+=$fqdn
        continue
    }
    
    #получаем текущий сертификат. Проверяем его срок действия
    $cert=Invoke-Command -session $session -scriptblock {
        import-module lync
        Get-CsCertificate -Type default
    }
    Remove-PSSession $session
    if ($now -ge $cert.notafter.adddays(-$days_warn)) {
        $servers_warn[$fqdn]=$cert.notafter
    }
}

# если есть подходящие к концу действия сертификаты или проблемы с подключением к серверам, написать письмо.
if (($servers_warn.count -ge 1) -or $failed_hosts) {
    $msg=""
    if($servers_warn.count -ge 1) {
        $msg+="на следующих серверах сертификаты истекают менее, чем через $days_warn"
        $msg+=""
        foreach($s in $servers_warn.keys) {
            $msg+=""
        }
        $msg+="
СерверСертификат истекает
"+$s+""+$servers_warn[$s]+"
" } if($failed_hosts.count -ge 1) { $msg+="При подключении к следующим серверам возникли проблемы" $msg+="" foreach($s in $failed_hosts) { $msg+="" } $msg+="
"+$s+"
" } $msg+="" Send-MailMessage -From $mail_from -to $mail_to -Subject "[Отчет] Обновление сертификатов Lync" -Body $msg -BodyAsHtml -Encoding ([System.Text.Encoding]::UTF8) -SmtpServer $mailserver }

Комментариев нет:

Отправить комментарий