Неожиданное истечение срока действия сертификата сервера может вызвать ряд неприятных последствий для ваших клиентов: невозможность установить безопасное подключение, ошибки аутентификации, назойливые предупреждения в браузере и т.д. В этой статье мы покажем, как с помощью PowerShell проверить срок действия SSL/TLS сертификатов на удаленных сайтах, а также истекающих сертификатах в хранилищах сертификатов на серверах и компьютерах домена.
Проверка срока действия SSL сертификата на веб-сайтах в Интернете с помощью PowerShell
Недавно сайт https://winitpro.ru/ был переведен на протокол HTTPS с помощью бесплатного SSL сертификата от Let’s Encrypt. Особенность этих сертификатов – они выдаются на срок 90 дней, после чего их нужно обновить (продлить). Обычно продление Let’s Encrypt сертификатов выполняется специальными скриптами или ботами на стороне хостинга или сервера (в Windows это может быть WACS, в Linux – Certbot). Но иногда автоматика может дать сбой. Мне хотелось бы иметь собственную систему проверки и оповещения об окончании срока действия SSL сертификатов на сайтах. Я реализовал ее на PowerShell. Т.к. мы проверяем сертификат сайта через HttpWeb запрос, вам не нужны права администратора на удаленном веб-сайте/сервере.
В следующем PowerShell скрипте нужно указать список сайтов, на которых нужно проверять срок действия сертификата, а также за сколько дней до окончания действия сертификата начинать показывать уведомления ($minCertAge). В качестве примера я указал 80 дней.
$minCertAge = 80
$timeoutMs = 10000
$sites = @(
"https://winitpro.ru",
"https://site1.com/",
"https://site2.ru/"
)
# Отключить проверку корректности сертификата
[Net.ServicePointManager]::ServerCertificateValidationCallback = {$true}
foreach ($site in $sites)
{
Write-Host Проверка $site -f Green
$req = [Net.HttpWebRequest]::Create($site)
$req.Timeout = $timeoutMs
try {$req.GetResponse() |Out-Null} catch {Write-Host Ошибка при проверке URL $site`: $_ -f Red}
[datetime]$certExpDate = $req.ServicePoint.Certificate.GetExpirationDateString()
[int]$certExpiresIn = ($certExpDate - $(get-date)).Days
$certName = $req.ServicePoint.Certificate.GetName()
$certThumbprint = $req.ServicePoint.Certificate.GetCertHashString()
$certEffectiveDate = $req.ServicePoint.Certificate.GetEffectiveDateString()
$certIssuer = $req.ServicePoint.Certificate.GetIssuerName()
if ($certExpiresIn -gt $minCertAge)
{Write-Host Сертификат для сайта $site истечет через $certExpiresIn дней [$certExpDate] -f Green}
else
{
$message= "Сертификат для сайта $site истечет через $certExpiresIn дней"
$messagetitle= "Продлить сертификат"
Write-Host $message [$certExpDate]. Подробности:`n`nCert name: $certName`Cert thumbprint: $certThumbprint`nCert effective date: $certEffectiveDate`nCert issuer: $certIssuer -f Red
#вывести всплывающее уведомление и отправить письмо администартору
#ShowNotification $messagetitle $message
# Send-MailMessage -From [email protected] -To [email protected] -Subject $messagetitle -body $message -SmtpServer smtp.winitpro.ru -Encoding UTF8
}
write-host "________________" `n
}
Данный PowerShell скрипт проверит SSL сертификаты для всех сайтов из списка. Если обнаружится сертификат, который скоро просрочится, он будет выдел в предупреждении.
Для оповещения администратора о приближающемся сроке истечения SSL сертификата можно добавить всплывающее уведомление. Для этого раскоментируйте строку ShowNotification $messagetitle $message и добавьте функцию:
Function ShowNotification ($MsgTitle, $MsgText) {
Add-Type -AssemblyName System.Windows.Forms
$global:balmsg = New-Object System.Windows.Forms.NotifyIcon
$path = (Get-Process -id $pid).Path
$balmsg.Icon = [System.Drawing.Icon]::ExtractAssociatedIcon($path)
$balmsg.BalloonTipIcon = [System.Windows.Forms.ToolTipIcon]::Warning
$balmsg.BalloonTipText = $MsgText
$balmsg.BalloonTipTitle = $MsgTitle
$balmsg.Visible = $true
$balmsg.ShowBalloonTip(10000)
}
Также можно добавит и email оповещение с помощью Send-MailMessage.
В результате при обнаружении просроченных или истекающих сертификатов вы будете уведомлены письмом и всплывающим сообщением
Осталось создать автоматическое задание планировщика, которые должно выполнятся 1-2 раза в неделю и запускать PowerShell скрипт проверки срока действия сертификатов HTTPS сайтов (вы можете создать задание планировщика для запуска PS1 файла с помощью Register-ScheduledTask).
Поиск истекающих сертификатов в хранилище сертификатов Windows
Также вам может понадобится скрипт, который будет мониторить срок действия сертификатов, используемых для криптографических службах на серверах (например сертификаты на RDS, Exchange, SharePoint, LDAPS и т.д) или компьютерах пользователей.
На локальном компьютере вы можете получить список сертификатов, которые скоро просрочатся с помощью команды
Get-ChildItem -Path cert
. В Powershell 3.0 есть специальный аргумент
-ExpiringInDays
:
Get-ChildItem -Path cert: -Recurse -ExpiringInDays 30
В PowerShell 2.0 аналогичная команда выглядит так:
Get-ChildItem -Path cert: -Recurse | where { $_.notafter -le (get-date).AddDays(30) -AND $_.notafter -gt (get-date)} | select thumbprint, subject
Чтобы проверить только собственные сертификаты, используйте контейнер
Cert:\LocalMachine\My
вместо корневого
Cert:
. Так вы не будете проверять корневые сертификаты Windows и коммерческие сертификаты.
Чтобы найти сертификаты, которые истекают в течении следующих 30 дней на всех серверах домена, можно использовать такой PowerShell скрипт:
$servers= (get-adcomputer -LDAPFilter "(&(objectCategory=computer)(operatingSystem=Windows Server*) (!serviceprincipalname=*MSClusterVirtualServer*) (!(userAccountControl:1.2.840.113556.1.4.803:=2)))").Name
$result=@()
foreach ($server in $servers)
{
$ErrorActionPreference="SilentlyContinue"
$getcert=Invoke-Command -ComputerName $server { Get-ChildItem -Path Cert:\LocalMachine\My -Recurse -ExpiringInDays 30}
foreach ($cert in $getcert) {
$result+=New-Object -TypeName PSObject -Property ([ordered]@{
'Server'=$server;
'Certificate'=$cert.Issuer;
'Expires'=$cert.NotAfter
})
}
}
Write-Output $result
Итак, вы получите список истекающих сертификатов на серверах и у вас будет достаточно времени для их продления.