Private/Checks/VCenter/Test-VcfVcenterVerifyCertificateExpirationdate.ps1
|
# Copyright (c) 2026 Broadcom. All Rights Reserved. # Broadcom Confidential. The term "Broadcom" refers to Broadcom Inc. # and/or its subsidiaries. # # ============================================================================= # # SOFTWARE LICENSE AGREEMENT # # Copyright (c) CA, Inc. All rights reserved. # # You are hereby granted a non-exclusive, worldwide, royalty-free license # under CA, Inc.'s copyrights to use, copy, modify, and distribute this # software in source code or binary form for use in connection with CA, Inc. # products. # # This copyright notice shall be included in all copies or substantial # portions of the software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS # IN THE SOFTWARE. # # ============================================================================= function Test-VcfVcenterVerifyCertificateExpirationdate { <# .SYNOPSIS Checks the vCenter machine SSL certificate and managed ESX host certificates for expiration across all vCenter domains. .DESCRIPTION Queries machine SSL certificates and managed ESX host certificates across all vCenter appliances connected to SDDC Manager using Get-VcfCheckMachineCertificate and Get-VcfCheckVMHostInventory. Evaluates certificate expiration dates against current time and the specified warning threshold: - Fail: One or more certificates are expired. - Warning: One or more certificates expire within WarningThresholdDays (default 30 days). - Pass: All checked certificates are valid and beyond WarningThresholdDays. Populates a structured Rows table detailing Cluster, Entity, EntityType, ExpiryDate, DaysRemaining, and Status. Delegates per-vCenter execution and per-domain outcome packaging to Invoke-VcfCheckPerVCenterCheck. .PARAMETER Context The VcfCheck.Context object. Must already be connected to SDDC Manager. .PARAMETER DisplayName Optional friendly display name for the check result. .PARAMETER WarningThresholdDays Number of days before expiry to raise a Warning instead of a Pass. Default 30. .OUTPUTS [PSObject[]] Per-vCenter check results generated by Invoke-VcfCheckPerVCenterCheck. #> [CmdletBinding()] [OutputType([PSObject])] Param ( [Parameter(Mandatory = $true)] [PSObject]$Context, [Parameter(Mandatory = $false)] [String]$DisplayName = '', [Parameter(Mandatory = $false)] [ValidateRange(1, 3650)] [Int]$WarningThresholdDays = 30 ) $now = Get-Date return Invoke-VcfCheckPerVCenterCheck -Context $Context -CheckId 'vcenter_verify_certificate_expirationdate' -Area vCenter -DisplayName $DisplayName -Body { param($Context, $VCenterFqdn) $certificates = @(Get-VcfCheckMachineCertificate -Server $VCenterFqdn) $vmHosts = @(Get-VcfCheckVMHostInventory -Server $VCenterFqdn) $clusterByHostName = @{} foreach ($vmHost in $vmHosts) { $cluster = Get-VcfCheckClusterForVMHost -VMHost $vmHost -Server $VCenterFqdn $clusterByHostName[$vmHost.Name] = if ($cluster) { $cluster.Name } else { '' } } $expired = [System.Collections.Generic.List[String]]::new() $expiringSoon = [System.Collections.Generic.List[String]]::new() $rows = @() foreach ($certificate in $certificates) { # Get-VIMachineCertificate's Entity is a VIObject (vCenter Server or VMHost), not a # string, and EntityType is the CertificateEntityType enum (VCenter/EsxHost) - both # render unreadably ("[object Object]"/the enum's underlying int) if passed through # as-is to a result Rows table, which only ever renders scalar values. $entityName = if ($certificate.Entity.Name) { $certificate.Entity.Name } else { $certificate.Entity.ToString() } $entityTypeLabel = $certificate.EntityType.ToString() $label = "$entityName ($entityTypeLabel)" $expiringWithinLabel = "Expiring Within $WarningThresholdDays Day(s)" $certStatus = 'Pass' if ($certificate.NotValidAfter -lt $now) { $expired.Add($label) $certStatus = 'Expired' } elseif ($certificate.NotValidAfter -lt $now.AddDays($WarningThresholdDays)) { $expiringSoon.Add($label) $certStatus = $expiringWithinLabel } $clusterName = if ($entityTypeLabel -eq 'EsxHost') { $clusterByHostName[$entityName] } else { 'N/A' } if ([String]::IsNullOrEmpty($clusterName)) { $clusterName = 'N/A' } $daysRemaining = [Math]::Floor(($certificate.NotValidAfter - $now).TotalDays) $rows += [PSCustomObject]@{ Cluster = $clusterName Entity = $entityName EntityType = $entityTypeLabel ExpiryDate = $certificate.NotValidAfter DaysRemaining = $daysRemaining Status = $certStatus } } $rows = @($rows | Sort-Object -Property Cluster, Entity) if ($expired.Count -gt 0) { $filteredRows = @($rows | Where-Object { $_.Status -eq 'Expired' }) return [PSCustomObject]@{ Status = 'Fail'; Detail = "Expired certificate(s): $($expired -join '; ')"; Rows = $filteredRows } } elseif ($expiringSoon.Count -gt 0) { $filteredRows = @($rows | Where-Object { $_.Status -eq "Expiring Within $WarningThresholdDays Day(s)" }) return [PSCustomObject]@{ Status = 'Warning'; Detail = "Certificate(s) expiring within $WarningThresholdDays day(s): $($expiringSoon -join '; ')"; Rows = $filteredRows } } else { return [PSCustomObject]@{ Status = 'Pass'; Detail = "Checked $($certificates.Count) certificate(s); none expired or expiring within $WarningThresholdDays day(s)."; Rows = $rows } } } } |