Управление сертификатами в крупномасштабных веб-средах — крупномасштабная проблема. У вас могут быть сотни серверов, служащих хостами для сотен веб-сайтов с поддержкой SSL, имеющих уникальные сертификаты. Если вы используете GUI IIS Manager, установка и обслуживание сертификатов в таком масштабе отнимет массу времени.
Не бойтесь — имеется лучший подход. Независимо от того, сколько у вас веб-серверов — два или 200, Windows PowerShell превратит дни, недели или месяцы потраченного вами времени в несколько минут. В процессе развертывания, установки и настройки сертификатов и SSL ваших веб-сайтов, можно применить несколько приемов, которые позволят найти сертификаты, которые вскоре устареют, и заменить их.
Принципы просты. Это работает в IIS 7.5 и IIS 8, но необходимо задействовать удаленный доступ через Windows PowerShell. В нашем примере будет два веб-сервера, работающих в конфигурации с балансированием нагрузки, и имеющих свои собственные IP-адреса кластера. На каждом сервере функционирует три веб-сайта, которым нужны SSL-сертификаты и привязки. Я изменил IP-адреса кластера на внутренние, чтобы скрыть настоящие веб-сайты, но идея должна быть вам понятна. Я приобрел сертификаты, и имею .pfx-файлы, готовые к развертыванию. Вот список моих веб-сайтов:
- Shop.Company.com — IP-адрес 192.168.3.201 — Сертификат: shop.company.com.pfx
- Update.Company.com — IP-адрес 192.168.3.202 — Сертификат: update.company.com.pfx
- Register.Company.com — IP-адрес 192.168.3.203 — Сертификат: register.company.com.pfx
Давайте приступим к развертыванию и установке сертификатов на веб-серверах с балансированием нагрузки.
Развертывание и установка
Для начала нам нужны две вещи — переменная, содержащая список имен компьютеров, являющихся веб-серверами, и удаленный сеанс соединения с каждым из этих серверов через Windows PowerShell. Имена компьютеров берутся из текстового файла с моего компьютера, но можно брать их и из Active Directory, если веб-серверы являются членами домена:
PS> $servers = Get-Content c:\webservers.txt
PS> $session = New-PsSession –ComputerName $servers
Скопируйте сертификаты на удаленные серверы, чтобы можно было без усилий установить их. Не опасайтесь, что кто-то украдет ваши .pfx-файлы. Вы удалите их в процессе выполнения операций, описанных в этом разделе. В нашем примере .pfx-файлы находятся на моем клиентском компьютере в каталоге c:\sites\certpfx:
PS> $servers | foreach-Object{
copy-item -Path c:\sites\certpfx\*.* -Destination "\\$_\c$"}
CertUtil.exe — отличное средство установки сертификатов из сеансов удаленного доступа через Windows PowerShell. В следующих однострочных командах осуществляется установка сертификатов на каждый веб-сервер. Нам нужно установить три сертификата (по одному для каждого веб-сайта), поэтому команда повторяется:
PS> Invoke-command -Session $session {
certutil -p P@ssw0rd -importpfx c:\shop.company.com.pfx}
PS> Invoke-command -Session $session {
certutil -p P@ssw0rd -importpfx c:\update.company.com.pfx}
PS> Invoke-command -Session $session {
certutil -p P@ssw0rd -importpfx c:\register.company.com.pfx}
При использовании CertUtil.exe потребуется указать пароли для .pfx. Поскольку я выполняю команды в реальном времени, я просто набираю пароли. Если вы собираетесь написать сценарий, я бы рекомендовал заменить пароли переменной для ввода пароля из приглашения, например:
PS> $Cred = (Get-Credential).password
Не забудьте удалить .pfx-файлы с удаленных веб-серверов, чтобы предотвратить потенциальное похищение сертификатов:
PS> $servers | foreach-object {Remove-Item -Path "\\$_\c$\*.pfx"}
Следующий шаг после установки сертификатов на удаленные серверы — создание HTTPS-привязок для веб-сайтов.
Создание привязок веб-сайтов
Каждый веб-сайт на каждом сервере в конфигурации с балансированием нагрузки должен иметь HTTPS-привязку. Воспользуйтесь командлетом New-WebBinding из модуля WebAdministration, и все будет проще простого. В параметрах командлета указывают имя сайта, протокол, порт и IP-адрес кластера для сайта. Параметр SSLFlags определяет местонахождение сертификата, который будет использоваться при привязке:
PS> Invoke-Command -session $session {Import-Module WebAdministration}
PS> Invoke-command -Session $session {
New-WebBinding -name shop -Protocol https -Port 443 -IPAddress 192.168.3.201 -SslFlags 0}
PS> Invoke-command -Session $session {
New-WebBinding -name update -Protocol https -Port 443 -IPAddress 192.168.3.202 -SslFlags 0}
PS> Invoke-command -Session $session {
New-WebBinding -name register -Protocol https -Port 443 -IPAddress 192.168.3.203 -SslFlags 0}
Мы только что установили сертификаты в хранилище сертификатов Windows. В нашем распоряжении были следующие варианты:
- 0 — обычный сертификат в хранилище сертификатов Windows;
- 1 — сертификат Server Name Indication (SNI);
- 2 — централизованное хранилище сертификатов;
- 3 — SNI-сертификат в централизованном хранилище сертификатов.
Остался последний шаг, который часто упускают из виду и забывают: связывание сертификатов с новыми привязками веб-сайтов.
Привязка сертификатов
На этом последнем шаге возможна путаница. Графический IIS Manager скрывает эту часть процесса, но мы не можем от нее отказаться, если хотим, чтобы наши сайты работали с SSL. Мы должны связать сертификаты с привязками веб-сайтов.
Это двухэтапный процесс. Во-первых, надо получить отпечаток (thumbprint) сертификата каждого веб-сайта, чтобы можно было создать соответствующую SSL-привязку. Вспомните: в нашем примере обслуживаются три веб-сайта. Мне нужен отпечаток каждого уникального сертификата. Я решил хранить отпечатки в трех различных переменных, чтобы не запутаться при их связывании с веб-сайтами:
PS> Invoke-Command -session $session {
$CertShop=Get-ChildItem -Path Cert:\LocalMachine\My |
where-Object {$_.subject -like "*shop*"} |
Select-Object -ExpandProperty Thumbprint}
PS> Invoke-Command -session $session {
$CertUpdate=Get-ChildItem -Path Cert:\LocalMachine\My |
where-Object {$_.subject -like "*update*"} |
Select-Object -ExpandProperty Thumbprint}
PS> Invoke-Command -session $session {
$CertRegister=Get-ChildItem -Path Cert:\LocalMachine\My |
where-Object {$_.subject -like "*register*"} |
Select-Object -ExpandProperty Thumbprint}
Теперь пора получить по отпечаткам сами сертификаты и указать их в SSL-привязках для каждого веб-сайта. Следующая команда использует Get-Item для получения сертификата, а затем New-Item для создания SSL-привязки; IIS-провайдер IIS:\SSLBindings создает SSL-привязки вместе с информацией о связывании:
PS> Invoke-Command -Session $session {
get-item -Path "cert:\localmachine\my\$certShop" |
new-item -path IIS:\SslBindings\192.168.3.201!443}
PS> Invoke-Command -Session $session {
get-item -Path "cert:\localmachine\my\$certUpdate" |
new-item -path IIS:\SslBindings\192.168.3.202!443}
PS> Invoke-Command -Session $session {
get-item -Path "cert:\localmachine\my\$certRegister" |
new-item -path IIS:\SslBindings\192.168.3.203!443}
В IIS информация о связывании обычно показывается как IP-адрес:порт:имя хоста (*:80:*). Однако Windows PowerShell интерпретирует двоеточие (:) как признак пути. Поэтому при использовании Windows PowerShell для задания информации о связывании вместо двоеточия используют восклицательный знак (!).
Теперь привязки сформированы, и можно обратиться к веб-сайтам по протоколу HTTPS:
PS> start iexplore https://shop.company.com
PS> start iexplore https://update.company.com
PS> start iexplore https://register.company.com
Проверка истечения
Имеется еще одно полезное решение, основанное на только что усвоенной вами информации. Для многих из вас это типичная производственная проблема: не устареют ли вскоре ваши сертификаты?
При управлении сертификатами приходится определять, не подходит ли к концу срок действия некоторых из них и не пора ли их заменить. К этой задаче применимы принципы и приемы, которые я описал выше. Но одной строкой здесь не обойдешься. И снова нужно открыть сеанс удаленного доступа через Windows PowerShell к веб-серверам, на которых вы собираетесь проверять срок действия сертификатов.
В следующем примере сканируются все сертификаты в хранилище сертификатов локального компьютера. Команда сравнивает свойство notafter, содержащее дату истечения сертификата, с текущей датой, и выводит результат в собственный столбец, названный мной ExpireInDays. Фильтр (Where-Object) служит для отбора сертификатов, до истечения которых осталось менее 90 дней. Команда выводит имена серверов и сертификаты, которые скоро устареют:
PS> Invoke-Command -Session $session {
Get-ChildItem -Path Cert:\LocalMachine\My |
Select-Object -Property PSComputerName, Subject, @{
n='ExpireInDays';e={($_.notafter - (Get-Date)).Days}} |
Where-Object {$_.ExpireInDays -lt 90}}
Используя усвоенные сегодня знания, вы сможете быстро и успешно заменить все такие сертификаты с помощью Windows PowerShell, даже в крупномасштабных конфигурациях.