Неожиданное истечение срока действия сертификата сервера может вызвать ряд неприятных последствий для ваших клиентов: невозможность установить безопасное подключение, ошибки аутентификации, назойливые предупреждения в браузере и т.д. В этой статье мы покажем, как с помощью 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
Итак, вы получите список истекающих сертификатов на серверах и у вас будет достаточно времени для их продления.
Пока не внес корректировку, ругался на формат даты
$certExpDate = [DateTime]::ParseExact(($req.ServicePoint.Certificate.GetExpirationDateString()), 'dd.MM.yyyy H:mm:ss', $null)
Спасибо за инфу! У меня мой скрипт работает корректно, вероятно это зависит от настроек формата локализации времени на компьютере.
Подскажите, а этот способ годится для проверки других сертификатов (не только SSL) ?
т.е. можно ли вбить список серверов в компании и успокоиться ?
Как скачать, спасибо
Строка 27:
Write-Host $message [$certExpDate]. Подробности:`n`nCert name: $certName`Cert thumbprint: $certThumbprint`nCert effective date: $certEffectiveDate`nCert issuer: $certIssuer -f Red
Где-то тут ошибка
вот простой скрипт для проверки валидности ssl сертификатов на нескольких сайтах _https://github.com/farismalaeb/Powershell/tree/master/CertificateScanner
Доброго дня,
спасибо за статью, как раз то что мне и нужно. Но у меня вопрос — а как отслеживать сертификат на токене? Есть USB — токен для доступа к определенному сайту госуслуг. Как мне отследить его валидность и вывести сообщение о скором истечении срока?
В каком формате там хранится сертфикат? В виде файла? Тип файла и защищен ли он ключом
Здравствуйте, он в виде диска в моем компьютере не отображается. только через Панель управления Рутокен
Как исключить отозванные??