param ( [string]$vCenter = "", [switch]$SaveCred = $false, [switch]$Help = $false ) # Variables $fileVersion = "1.1.0" $fileDate = "2025-04-02" # Display Script Banner Write-Host "--------------------------------------------------" -ForegroundColor White Write-Host "vSphere TPM Key Inventory" -ForegroundColor Green Write-Host "Version $($FileVersion) ($($FileDate))" -ForegroundColor Green Write-Host "Written by Charlie Silverman" -ForegroundColor Green Write-Host "--------------------------------------------------" -ForegroundColor White if ($Help) { Write-Host Write-Host "Purpose: Collect TPM encryption keys for all ESXi hosts." Write-Host "Command Syntax:" Write-Host " GetKeys.ps1 (-vcenter [vcenter host name]) (-savecred) (-help)" Write-Host "Command Line Options:" Write-Host Write-Host -NoNewLine " -vCenter " -foregroundcolor Green Write-Host "- The FQDN or IP address of a vCenter server." Write-Host -NoNewLine " -savecred " -foregroundcolor Green Write-Host "- Configure and store vCenter server credentials. This will only store the credentials under" Write-Host " the current logged in user." Write-Host -NoNewLine " -help " -foregroundcolor Green Write-Host "- Display command help." Write-Host Write-Host "If no any of the information is not provided, you will be prompted. If a credential has been previously stored, it will be used again unless the -savecred option is specified." Write-Host exit } if (-not (Get-Module -ListAvailable -Name VMware.PowerCLI*)) { Write-Host "ERROR: VMware PowerCLI is not installed!" -foregroundcolor yellow exit } $hideresult = Set-PowerCLIConfiguration -InvalidCertificateAction Ignore -Confirm:$false if ($vCenter -eq "") { $vCenter = Read-Host "Enter name of vCenter Server" } if ($savecred) { $credential = Get-Credential -Message "Enter credentials for vCenter server $vcenter" $credential | Export-Clixml -path $env:USERPROFILE\kis-getkeys-$vcenter.cred Write-Host "Saving credentials." } if (Test-Path -path $env:USERPROFILE\kis-getkeys-$vcenter.cred -PathType Leaf) { $credentials = Import-Clixml -path $env:USERPROFILE\kis-getkeys-$vcenter.cred Write-Host "Using stored credentials" } else { $credentials = Get-Credential -Message "Enter credentials for vCenter server $vcenter" if (!$credentials) { Write-Host "ERROR: No credentials were entered" -foregroundcolor yellow } } try { Write-Host -NoNewLine "Connecting to vCenter $vcenter..." $vcconn = Connect-VIServer $vcenter -Credential $credentials -ErrorAction SilentlyContinue Write-Host " Success" -ForegroundColor green } catch { Write-Host " Failure" -ForegroundColor Yellow -BackgroundColor Red exit } $now = (Get-Date).ToString("yyyyMMdd_hhmm") $exportfile = "TPMKeys-$vCenter-$now.csv" $VMHosts = Get-VMHost | Sort-Object $VMHostKeys = @() foreach ($VMHost in $VMHosts) { $esxcli = Get-EsxCli -VMHost $VMHost -V2 try { $encryption = $esxcli.system.settings.encryption.get.Invoke() if ($encryption.Mode -eq "TPM") { $key = $esxcli.system.settings.encryption.recovery.list.Invoke() $hostKey = [pscustomobject]@{ Host = $VMHost.Name EncryptionMode = $encryption.Mode RequireExecutablesOnlyFromInstalledVIBs = $encryption.RequireExecutablesOnlyFromInstalledVIBs RequireSecureBoot = $encryption.RequireSecureBoot RecoveryID = $key.RecoveryID RecoveryKey = $key.Key } $VMHostKeys += $hostKey } else { $hostKey = [pscustomobject]@{ Host = $VMHost.Name EncryptionMode = $encryption.Mode RequireExecutablesOnlyFromInstalledVIBs = $encryption.RequireExecutablesOnlyFromInstalledVIBs RequireSecureBoot = $encryption.RequireSecureBoot RecoveryID = $null RecoveryKey = $null } $VMHostKeys += $hostKey } } catch { $VMHost.Name + $_ } } Write-Host "Exporting TPM keys for all hosts in $vcenter`n to $exportfile..." -NoNewLine try { $VMHostKeys | Export-Csv $exportfile Write-Host " Complete" -ForegroundColor Green } catch { Write-Host " Failed" -ForegroundColor Red exit } Write-Host "Attempting to reset all TPM Encryption Recovery Key Backup Alarms..." # Locate TPM Encrytpion Recovery Key Backup Alarm ID $alarm = Get-AlarmDefinition "TPM Encryption Recovery Key Backup Alarm" $alarmID = $alarm.Id -split '-', 2 | select-object -last 1 $alarmMgr = Get-View AlarmManager foreach ($VMHost in $VMHosts) { try { $decalarm = $VMHost.ExtensionData.TriggeredAlarmState | where-object {$_.Alarm.Value -eq $alarmID} | Select-Object -first 1 if ([string]::IsNullorEmpty($decalarm)) { continue } } catch { Write-Host "Error retrieving alarms for host $VMHost" continue } } Write-Host "Clearing all yellow alarms from ESXi hosts..." try { $filter = New-Object VMware.Vim.AlarmFilterSpec $filter.Status += [VMware.Vim.ManagedEntityStatus]::yellow $filter.TypeEntity = [VMware.Vim.AlarmFilterSpecAlarmTypeByEntity]::entityTypeHost $filter.TypeTrigger = [vmware.vim.AlarmFilterSpecAlarmTypeByTrigger]::triggerTypeAll $alarmMgr.ClearTriggeredAlarms($filter) Write-Host " Success" -ForegroundColor Green } catch { Write-Host " Failed" -ForegroundColor Red }