Накидал быстрый чек-скриптl, который опрашивает хосты/порты и показывает, когда сертификат сгорит.
Быстрый чек одного хоста
$HostName = 'site.contoso.com'
$Port = 443
$tcp = [Net.Sockets.TcpClient]::new($HostName, $Port)
$ssl = [Net.Security.SslStream]::new($tcp.GetStream(), $false, { $true })
$ssl.AuthenticateAsClient($HostName)
$cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new($ssl.RemoteCertificate)
[pscustomobject]@{
Host = $HostName
Port = $Port
Subject = $cert.Subject
NotAfter = $cert.NotAfter
DaysLeft = [math]::Floor(($cert.NotAfter - (Get-Date)).TotalDays)
}
$ssl.Dispose(); $tcp.Close()
Скан нескольких целей + статус
$targets = @(
'site1.contoso.com:443',
'mail.contoso.com:993',
'rdgw.contoso.com:443'
)
$result = foreach ($t in $targets) {
$host,$port = $t.Split(':',2)
try {
$tcp = [Net.Sockets.TcpClient]::new($host,[int]$port)
$ssl = [Net.Security.SslStream]::new($tcp.GetStream(), $false, { $true })
$ssl.AuthenticateAsClient($host)
$cert = [Security.Cryptography.X509Certificates.X509Certificate2]::new($ssl.RemoteCertificate)
$days = [math]::Floor(($cert.NotAfter - (Get-Date)).TotalDays)
[pscustomobject]@{
Host = $host
Port = [int]$port
CN = $cert.GetNameInfo('SimpleName',$false)
NotAfter = $cert.NotAfter
DaysLeft = $days
Status = if ($days -le 14) { '🔥 expiring ≤14d' }
elseif ($days -le 30) { '⚠️ <30d' }
else { '✅ ok' }
}
}
catch {
[pscustomobject]@{
Host=$host; Port=[int]$port; CN=$null; NotAfter=$null; DaysLeft=$null
Status="❌ error: $($_.Exception.Message)"
}
}
finally {
if ($ssl) { $ssl.Dispose() }
if ($tcp) { $tcp.Close() }
}
}
$result | Sort-Object DaysLeft | Format-Table -AutoSize
# Для отчёта:
# $result | Export-Csv .\tls_report.csv -NoTypeInformation -Encoding UTF8
Плюс: можно крутить по расписанию в Task Scheduler и слать уведомления, если
DaysLeft ≤ 30. Спасает от «неожиданных» падений продакшна.👉 @win_sysadmin