Active Directory
banshee/active-directory-collection/active-directory/winrm/
adcs
The service of an Active Directory certification authority and the days before its certificate expires, by WinRM and PowerShell
by banshee1 installation3 versions
// The certification authority of Active Directory Certificate Services, by WinRM: the state of its service,
// CertSvc, and the days left before its certificate expires. Once it expires, nothing it issued is trusted.
// Runs one PowerShell script that only reads: Win32_Service for the service CertSvc, and the certificates
// (.crt) the authority publishes in its folder CertEnroll (System32\CertSrv\CertEnroll), read by the class
// X509Certificate2 of .NET; the one that expires last is the current certificate of the authority, the
// former ones staying beside it after a renewal.
// The expiry of the certificate revocation list (CRL) is read by active-directory/https/crl, at its
// distribution point: the .NET Framework of Windows PowerShell has no class that reads a CRL.
// The script is the one of active-directory/ssh/adcs, without the powershell -Command "..." that cmd.exe
// needs there.
need('protocol:winrm');
output('service', 'text', array('label' => 'Certificate Services'));
output('certificate', 'text', array('label' => 'Certificate of the authority'));
output('days-left', 'number', array('label' => 'Before the certificate expires', 'unit' => 'd'));
watch.expect('service-stopped', 'Certificate Services stopped', 'service', array('critical' => array('running')));
watch.below('expiring', 'Authority certificate expiring', 'days-left', array('warning' => 180, 'critical' => 60));
$read = winrm.run("$ErrorActionPreference = 'Stop'; "
. "[Console]::OutputEncoding = New-Object System.Text.UTF8Encoding; "
. "$state = [string](Get-CimInstance Win32_Service -Filter 'Name=''CertSvc''').State; "
. "$folder = Join-Path $env:windir 'System32\\CertSrv\\CertEnroll'; "
. "$subject = ''; $days = ''; "
. "if (Test-Path $folder) {"
. " $latest = Get-ChildItem $folder -Filter '*.crt'"
. " | ForEach-Object { New-Object Security.Cryptography.X509Certificates.X509Certificate2($_.FullName) }"
. " | Sort-Object NotAfter | Select-Object -Last 1;"
. " if ($latest) { $subject = $latest.Subject;"
. " $days = [long]($latest.NotAfter.ToUniversalTime() - [DateTime]::UtcNow).TotalDays } }; "
. "ConvertTo-Json -Compress -InputObject @{service = $state; subject = $subject; days = $days}");
$answer = text.trim($read['output']);
if (list.count(text.match($answer, '^\{')) == 0) {
fail('misconfigured', 'PowerShell did not return the certification authority', $answer . $read['errors']);
}
$authority = json.read($answer);
if ($authority['service'] == '') {
fail('misconfigured', 'Active Directory Certificate Services is not installed', $answer);
}
if ($authority['days'] == '') {
fail('misconfigured', 'No certificate of the authority in its CertEnroll folder', $answer);
}
// The state of the service is written by WMI in English: "Running", "Stopped", "Start Pending"...
value('service', text.lower(text.join(text.words($authority['service']), '-')));
value('certificate', $authority['subject']);
value('days-left', $authority['days']);