Public/Test-AnyStackCertificates.ps1
|
function Test-AnyStackCertificates { <# .SYNOPSIS Tests host certificate validity. .DESCRIPTION Checks expiration dates of ESXi host certificates. .PARAMETER Server vCenter Server hostname or VIServer object. Uses active connection if omitted. .PARAMETER ClusterName Filter by cluster name. .PARAMETER WarnDays Warning threshold in days (default 60). .EXAMPLE PS> Test-AnyStackCertificates .OUTPUTS PSCustomObject .NOTES Author: The AnyStack Architect Requires: VCF.PowerCLI 9.0+, vSphere 8.0 U3+ #> [CmdletBinding(SupportsShouldProcess=$false)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [ValidateNotNull()] $Server, [Parameter(Mandatory=$false)] [string]$ClusterName, [Parameter(Mandatory=$false)] [int]$WarnDays = 60 ) begin { $vi = Get-AnyStackConnection -Server $Server $ErrorActionPreference = 'Stop' } process { try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Checking certificates on $($vi.Name)" $hosts = Invoke-AnyStackWithRetry -ScriptBlock { Get-View -Server $vi -ViewType HostSystem -Property Name,Config.Certificate } foreach ($h in $hosts) { if ($h.Config.Certificate) { $certBytes = $h.Config.Certificate[0] $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certBytes) $days = [int]($cert.NotAfter - (Get-Date)).TotalDays [PSCustomObject]@{ PSTypeName = 'AnyStack.CertificateStatus' Timestamp = (Get-Date) Server = $vi.Name Host = $h.Name Subject = $cert.Subject Issuer = $cert.Issuer ExpiresOn = $cert.NotAfter DaysRemaining = $days Status = if ($days -lt $WarnDays) { 'WARNING' } else { 'OK' } } } } } catch { $PSCmdlet.ThrowTerminatingError([System.Management.Automation.ErrorRecord]::new(function Test-AnyStackCertificates { <# .SYNOPSIS Tests host certificate validity. .DESCRIPTION Checks expiration dates of ESXi host certificates. .PARAMETER Server vCenter Server hostname or VIServer object. Uses active connection if omitted. .PARAMETER ClusterName Filter by cluster name. .PARAMETER WarnDays Warning threshold in days (default 60). .EXAMPLE PS> Test-AnyStackCertificates .OUTPUTS PSCustomObject .NOTES Author: The AnyStack Architect Requires: VCF.PowerCLI 9.0+, vSphere 8.0 U3+ #> [CmdletBinding(SupportsShouldProcess=$false)] [OutputType([PSCustomObject])] param( [Parameter(Mandatory=$false, ValueFromPipeline=$true)] [ValidateNotNull()] $Server, [Parameter(Mandatory=$false)] [string]$ClusterName, [Parameter(Mandatory=$false)] [int]$WarnDays = 60 ) begin { $vi = Get-AnyStackConnection -Server $Server $ErrorActionPreference = 'Stop' } process { try { Write-Verbose "[$($MyInvocation.MyCommand.Name)] Checking certificates on $($vi.Name)" $hosts = Invoke-AnyStackWithRetry -ScriptBlock { Get-View -Server $vi -ViewType HostSystem -Property Name,Config.Certificate } foreach ($h in $hosts) { if ($h.Config.Certificate) { $certBytes = $h.Config.Certificate[0] $cert = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($certBytes) $days = [int]($cert.NotAfter - (Get-Date)).TotalDays [PSCustomObject]@{ PSTypeName = 'AnyStack.CertificateStatus' Timestamp = (Get-Date) Server = $vi.Name Host = $h.Name Subject = $cert.Subject Issuer = $cert.Issuer ExpiresOn = $cert.NotAfter DaysRemaining = $days Status = if ($days -lt $WarnDays) { 'WARNING' } else { 'OK' } } } } } catch { $PSCmdlet.ThrowTerminatingError([System.Management.Automation.ErrorRecord]::new($_, 'UnexpectedError', [System.Management.Automation.ErrorCategory]::NotSpecified, $null)) } } } .Exception, 'UnexpectedError', [System.Management.Automation.ErrorCategory]::NotSpecified, $null)) } } } |