Skip to content

Commit 79d8355

Browse files
tpcarmanclaude
andcommitted
Fix vCenter certificate section showing VMCA template defaults (#88)
Replace vpxd.certmgmt.certs.cn.* advanced settings reads with a direct TLS connection to port 443, returning the actual deployed certificate. Use SslStream with an explicit-parameter RemoteCertificateValidationCallback for reliable PS 5.1 and 7.x compatibility. Certificate status (VALID / EXPIRING_SOON / EXPIRING / EXPIRED) is computed from NotAfter vs the existing soft/hard threshold advanced settings. Fields removed: Country, Email, Locality, State, Organization, OrganizationUnit, Validity (VMCA template settings — not the live cert). Fields added: Subject, Issuer, ValidFrom, ValidTo, Thumbprint, CertStatus. All five locale files (en-US, en-GB, es-ES, fr-FR, de-DE) updated. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent 51bddf1 commit 79d8355

7 files changed

Lines changed: 84 additions & 57 deletions

File tree

AsBuiltReport.VMware.vSphere/Language/de-DE/VMwarevSphere.psd1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ GetAbrVSpherevCenter = ConvertFrom-StringData @'
6262
Available = Verfügbar
6363
Expiration = Ablauf
6464
Certificate = Zertifikat
65-
Country = Land
66-
Email = E-Mail
67-
Locality = Ort
68-
State = Bundesland
69-
Organization = Organisation
70-
OrganizationUnit = Organisationseinheit
71-
Validity = Gültigkeit
65+
Subject = Betreff
66+
Issuer = Aussteller
67+
ValidFrom = Gültig ab
68+
ValidTo = Gültig bis
69+
Thumbprint = Fingerabdruck
70+
CertStatus = Status
71+
InsufficientPrivCertificate = Das vCenter Server-Zertifikat konnte nicht abgerufen werden. {0}
7272
Mode = Modus
7373
SoftThreshold = Weicher Schwellenwert
7474
HardThreshold = Harter Schwellenwert

AsBuiltReport.VMware.vSphere/Language/en-GB/VMwarevSphere.psd1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ GetAbrVSpherevCenter = ConvertFrom-StringData @'
6262
Available = Available
6363
Expiration = Expiration
6464
Certificate = Certificate
65-
Country = Country
66-
Email = Email
67-
Locality = Locality
68-
State = State
69-
Organization = Organization
70-
OrganizationUnit = Organization Unit
71-
Validity = Validity
65+
Subject = Subject
66+
Issuer = Issuer
67+
ValidFrom = Valid From
68+
ValidTo = Valid To
69+
Thumbprint = Thumbprint
70+
CertStatus = Status
71+
InsufficientPrivCertificate = Unable to retrieve vCenter Server certificate. {0}
7272
Mode = Mode
7373
SoftThreshold = Soft Threshold
7474
HardThreshold = Hard Threshold

AsBuiltReport.VMware.vSphere/Language/en-US/VMwarevSphere.psd1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ GetAbrVSpherevCenter = ConvertFrom-StringData @'
6262
Available = Available
6363
Expiration = Expiration
6464
Certificate = Certificate
65-
Country = Country
66-
Email = Email
67-
Locality = Locality
68-
State = State
69-
Organization = Organization
70-
OrganizationUnit = Organization Unit
71-
Validity = Validity
65+
Subject = Subject
66+
Issuer = Issuer
67+
ValidFrom = Valid From
68+
ValidTo = Valid To
69+
Thumbprint = Thumbprint
70+
CertStatus = Status
71+
InsufficientPrivCertificate = Unable to retrieve vCenter Server certificate. {0}
7272
Mode = Mode
7373
SoftThreshold = Soft Threshold
7474
HardThreshold = Hard Threshold

AsBuiltReport.VMware.vSphere/Language/es-ES/VMwarevSphere.psd1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ GetAbrVSpherevCenter = ConvertFrom-StringData @'
6262
Available = Disponible
6363
Expiration = Vencimiento
6464
Certificate = Certificado
65-
Country = País
66-
Email = Correo electrónico
67-
Locality = Localidad
68-
State = Estado
69-
Organization = Organización
70-
OrganizationUnit = Unidad organizativa
71-
Validity = Validez
65+
Subject = Asunto
66+
Issuer = Emisor
67+
ValidFrom = Válido desde
68+
ValidTo = Válido hasta
69+
Thumbprint = Huella digital
70+
CertStatus = Estado
71+
InsufficientPrivCertificate = No se puede recuperar el certificado del servidor vCenter. {0}
7272
Mode = Modo
7373
SoftThreshold = Umbral suave
7474
HardThreshold = Umbral estricto

AsBuiltReport.VMware.vSphere/Language/fr-FR/VMwarevSphere.psd1

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -62,13 +62,13 @@ GetAbrVSpherevCenter = ConvertFrom-StringData @'
6262
Available = Disponible
6363
Expiration = Expiration
6464
Certificate = Certificat
65-
Country = Pays
66-
Email = E-mail
67-
Locality = Localité
68-
State = État
69-
Organization = Organisation
70-
OrganizationUnit = Unité organisationnelle
71-
Validity = Validité
65+
Subject = Sujet
66+
Issuer = Émetteur
67+
ValidFrom = Valide à partir de
68+
ValidTo = Valide jusqu'au
69+
Thumbprint = Empreinte numérique
70+
CertStatus = Statut
71+
InsufficientPrivCertificate = Impossible de récupérer le certificat du serveur vCenter. {0}
7272
Mode = Mode
7373
SoftThreshold = Seuil souple
7474
HardThreshold = Seuil strict

AsBuiltReport.VMware.vSphere/Src/Private/Get-AbrVSpherevCenter.ps1

Lines changed: 48 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -199,29 +199,55 @@ function Get-AbrVSpherevCenter {
199199
#region vCenter Server Certificate
200200
if ($vCenter.Version -ge 6) {
201201
Section -Style Heading3 $LocalizedData.Certificate {
202-
$VcenterCertMgmt = [PSCustomObject]@{
203-
$LocalizedData.Country = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.country' }).Value
204-
$LocalizedData.Email = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.email' }).Value
205-
$LocalizedData.Locality = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.localityName' }).Value
206-
$LocalizedData.State = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.state' }).Value
207-
$LocalizedData.Organization = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.organizationName' }).Value
208-
$LocalizedData.OrganizationUnit = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.cn.organizationalUnitName' }).Value
209-
$LocalizedData.Validity = "$(($vCenterAdvSettings | Where-Object {$_.name -eq 'vpxd.certmgmt.certs.daysValid'}).Value / 365) years"
210-
$LocalizedData.Mode = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.mode' }).Value
211-
$LocalizedData.SoftThreshold = "$(($vCenterAdvSettings | Where-Object {$_.name -eq 'vpxd.certmgmt.certs.softThreshold'}).Value) days"
212-
$LocalizedData.HardThreshold = "$(($vCenterAdvSettings | Where-Object {$_.name -eq 'vpxd.certmgmt.certs.hardThreshold'}).Value) days"
213-
$LocalizedData.MinutesBefore = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.minutesBefore' }).Value
214-
$LocalizedData.PollInterval = "$(($vCenterAdvSettings | Where-Object {$_.name -eq 'vpxd.certmgmt.certs.pollIntervalDays'}).Value) days"
215-
}
216-
$TableParams = @{
217-
Name = ($LocalizedData.TableCertificate -f $vCenterServerName)
218-
List = $true
219-
ColumnWidths = 40, 60
220-
}
221-
if ($Report.ShowTableCaptions) {
222-
$TableParams['Caption'] = "- $($TableParams.Name)"
202+
try {
203+
$SslCallback = [System.Net.Security.RemoteCertificateValidationCallback]{
204+
param($sender, $cert, $chain, $errors) $true
205+
}
206+
$TcpClient = New-Object -TypeName System.Net.Sockets.TcpClient -ArgumentList ($vCenterServerName, 443)
207+
$SslStream = New-Object -TypeName System.Net.Security.SslStream -ArgumentList (
208+
$TcpClient.GetStream(), $false, $SslCallback
209+
)
210+
$SslStream.AuthenticateAsClient($vCenterServerName)
211+
$VIMachineCert = [System.Security.Cryptography.X509Certificates.X509Certificate2]$SslStream.RemoteCertificate
212+
$SslStream.Dispose()
213+
$TcpClient.Dispose()
214+
$SoftThresholdDays = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.softThreshold' }).Value
215+
$HardThresholdDays = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.hardThreshold' }).Value
216+
$DaysRemaining = ($VIMachineCert.NotAfter - (Get-Date)).Days
217+
$CertificateStatus = if ($DaysRemaining -le 0) {
218+
'EXPIRED'
219+
} elseif ($null -ne $HardThresholdDays -and $DaysRemaining -le [int]$HardThresholdDays) {
220+
'EXPIRING'
221+
} elseif ($null -ne $SoftThresholdDays -and $DaysRemaining -le [int]$SoftThresholdDays) {
222+
'EXPIRING_SOON'
223+
} else {
224+
'VALID'
225+
}
226+
$VcenterCertMgmt = [PSCustomObject]@{
227+
$LocalizedData.Subject = $VIMachineCert.Subject
228+
$LocalizedData.Issuer = $VIMachineCert.Issuer
229+
$LocalizedData.ValidFrom = $VIMachineCert.NotBefore
230+
$LocalizedData.ValidTo = $VIMachineCert.NotAfter
231+
$LocalizedData.Thumbprint = $VIMachineCert.Thumbprint
232+
$LocalizedData.CertStatus = $CertificateStatus
233+
$LocalizedData.Mode = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.mode' }).Value
234+
$LocalizedData.SoftThreshold = "$(($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.softThreshold' }).Value) days"
235+
$LocalizedData.HardThreshold = "$(($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.hardThreshold' }).Value) days"
236+
$LocalizedData.MinutesBefore = ($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.minutesBefore' }).Value
237+
$LocalizedData.PollInterval = "$(($vCenterAdvSettings | Where-Object { $_.name -eq 'vpxd.certmgmt.certs.pollIntervalDays' }).Value) days"
238+
}
239+
$TableParams = @{
240+
Name = ($LocalizedData.TableCertificate -f $vCenterServerName)
241+
List = $true
242+
ColumnWidths = 40, 60
243+
}
244+
if ($Report.ShowTableCaptions) {
245+
$TableParams['Caption'] = "- $($TableParams.Name)"
246+
}
247+
$VcenterCertMgmt | Table @TableParams
248+
} catch {
249+
Write-PScriboMessage -IsWarning ($LocalizedData.InsufficientPrivCertificate -f $_.Exception.Message)
223250
}
224-
$VcenterCertMgmt | Table @TableParams
225251
}
226252
}
227253
#endregion vCenter Server Certificate

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1111

1212
### Fixed
1313

14+
- Fix vCenter Server Certificate section reporting VMCA template defaults instead of the actual deployed TLS certificate; now reads the live certificate directly from port 443 ([#88](https://github.com/AsBuiltReport/AsBuiltReport.VMware.vSphere/issues/88))
1415
- Fix null disk group crash in OSA vSAN clusters where disk groups have not yet been claimed ([#113](https://github.com/AsBuiltReport/AsBuiltReport.VMware.vSphere/issues/113))
1516
- Fix `An item with the same key has already been added. Key: LinkedView` error when generating TEXT format reports ([#130](https://github.com/AsBuiltReport/AsBuiltReport.VMware.vSphere/issues/130))
1617
- Fix "Index operation failed; the array index evaluated to null" crash and `Global.Licenses` privilege errors when querying ESXi host/vCenter licensing on vCenter 8.0.2 ([#123](https://github.com/AsBuiltReport/AsBuiltReport.VMware.vSphere/issues/123))

0 commit comments

Comments
 (0)