PowerCLI script : How to confirm a vCenter server, ESXi VMware hypervisor & microcode patches are applied?: Spectre vulnerability

Some time back, VMware has released one of important KBs on “Hypervisor-Assisted Guest Mitigation for branch target injection”. Please take a look at this KB here. In this KB, there is one important section on “how to confirm a host has both patched microcode and patched VMware hypervisor?” and below is what is posted on KB.

Confirmation of Correct Operation
To confirm a host has both patched microcode and patched VMware hypervisor, use the following steps:
1.Power on a Virtual Machine which is configured to use Virtual Hardware Version 9 or later.
2.Examine the vmware.log file for that VM and look for one of the following entries:
“Capability Found: cpuid.IBRS”
“Capability Found: cpuid.IBPB”
“Capability Found: cpuid.STIBP”
3. Any of the above log entries indicates that both the CPU microcode and hypervisor are properly updated.

I thought it would be really handy if we automate it using PowerCLI including right vCenter server patch. Accordingly, I started looking for any existing cmdlets which can help me to retrieve the VM logs (specially vmware.log) and I could see PowerCLI guru Luc Dekens had written a article on retrieving VM logs long back. I leveraged the same and came up with one quick PowerCLI script to confirm whether a host has both patched microcode and patched VMware hypervisor or not. Here we go.

Update 01/13: As per latest update from VMware on KB, I have published another PowerCLI script, I recommend you to take a look at it before reading this post further.

Script execution steps:
i) First it validates whether vCenter is patched to correct build or not (builds are compared with build specified in respective release notes).
ii) After that, it gets all the connected hosts inside the specified cluster. It can be easily modified to consider host from particular datacenter as mentioned above.
iii) It will then iterate through each host in sequence and create a dummyVM.
iv) DRS automation on created dummyVM will be disabled since we need to powerON the VM and if DRS is enabled on the cluster, as part of DRS initial placement workflow, it may place/powerON the VM on some other host inside the cluster.
v) Now it will powerON the dummyVM
vi) Download the vmware.log file at specified location
vii) Scan for the log lines specified in KB (posted above) & record the results.
viii) PowerOff the created VM (to avoid any disk space utilization, you can choose to delete this VM as well)
ix) Step iii) through viii) will repeated for every host inside the cluster.
x) Finally log the result into one CSV file. CSV file will have HostName & Status (Patched or Un-Patched). Refer CSV sample below.

Update 01/10: Added vCenter server patch validation code as well. Now this script can provide you report on whether vCenter, ESXi VMware hypervisor & ESXi host microcode patches are applied or not. It is already added into below script.

Update 01/11: Below code will consider all hosts from particular datacenter (it will cover all clusters from that DC as well) instead of just cluster. By default script will take hosts from specified cluster, to consider all hosts from datacenter, please replace line #106 through #110 with below lines and do change “ResourcePool” parameter passed to New-VM cmdlet, which creates the VM.

$DCName="IndiaDC" # VC datacenter name, script assumes that datacenter is available
$dc= Get-Datacenter -Name $DCName

#Get connected hosts from above datacenter
$esxhosts = Get-Datacenter $dc | Get-VMHost -State Connected

Below script is available on my git-hub repo as well

<# .SYNOPSIS PowerCLI script:For spectre vulnerability : "How to confirm whether vCenter server, ESXi hypervisor & CPU microcode patches are applied or not?" .NOTES Author: Vikas Shitole .NOTES Site: www.vThinkBeyondVM.com .NOTES Please add the vCenter server IP/credetails as per your environment .NOTES Relese notes: VC 6.5 U1e: https://docs.vmware.com/en/VMware-vSphere/6.5/rn/vsphere-vcenter-server-65u1e-release-notes.html VC 6.0 U3d: https://docs.vmware.com/en/VMware-vSphere/6.0/rn/vsphere-vcenter-server-60u3d-release-notes.html VC 5.5 U3g: https://docs.vmware.com/en/VMware-vSphere/5.5/rn/vsphere-vcenter-server-55u3g-release-notes.html #>

#vCenter Connection, please modify as per your env.

Connect-VIServer -Server -Protocol https -User administrator@vsphere.local -Password VMware!32

function Get-VMLog{
<# .SYNOPSIS Retrieve the virtual machine logs .DESCRIPTION The function retrieves the logs from one or more virtual machines and stores them in a local folder .NOTES Author: Luc Dekens .PARAMETER VM The virtual machine(s) for which you want to retrieve the logs. .PARAMETER Path The folderpath where the virtual machines logs will be stored. The function creates a folder with the name of the virtual machine in the specified path. .EXAMPLE PS> Get-VMLog -VM $vm -Path "C:\VMLogs"
	PS> Get-VM | Get-VMLog -Path "C:\VMLogs"
		foreach($obj in $VM){
			if($obj.GetType().Name -eq "string"){
				$obj = Get-VM -Name $obj
		$logPath = $obj.Extensiondata.Config.Files.LogDirectory
		$dsName = $logPath.Split(']')[0].Trim('[')
		$vmPath = $logPath.Split(']')[1].Trim(' ')
		$ds = Get-Datastore -Name $dsName
		$drvName = "MyDS" + (Get-Random)
		New-PSDrive -Location $ds -Name $drvName -PSProvider VimDatastore -Root '\' | Out-Null
		Copy-DatastoreItem -Item ($drvName + ":" + $vmPath + "vmware.log") -Destination ($Path + "\" + $obj.Name + "\") -Force:$true
		Remove-PSDrive -Name $drvName -Confirm:$false
$report = @()

#As per release notes: vCenter builds which provide part of the hypervisor-assisted guest remediation of CVE-2017-5715 for guest operating systems 
$vc65u1eBuild = "7515524" #VC 6.5 U1e build

$vc60u3dBuild = "7464194" #VC 6.0 u3e build

$vc55u3gBuild = "7460778" #VC 5.5 u3g build

#getting service-Instance object to get vCenter build details
$Si = Get-View ServiceInstance
$vcVersion = $Si.Content.About.ApiVersion
$vcBuild = $Si.Content.About.Build

if (($vcBuild -eq $vc65u1eBuild) -or ($vcBuild -eq $vc60u3deBuild) -or ($vcBuild -eq $vc55u3gBuild )) {
	Write-Host "vCenter build is matching with build specified on release notes"
	Write-Host "vCenter build number::" $vcBuild
	Write-Host "vCenter build & version ::" $vcBuildVersion
	Write-Host "VC is patched to correct build"
	$row = '' | select HostName, Status
 	$row.HostName = $vcBuildVersion
 	$report += $row
}Else {
    Write-Host "vCenter build is NOT matching with build specified on release notes"
	Write-Host "vCenter build number::" $vcBuild
	Write-Host "vCenter build & version ::" $vcBuildVersion
	Write-Host "VC is NOT patched to correct build, please upgrade vCenter server."
	$row = '' | select HostName, Status
 	$row.HostName = $vcBuildVersion
 	$report += $row

#Location where vmware.log file gets downloaded

# Any of below lines must be found in vmware.log file to confirm microcode & VMware hypervisor patch
$pat1='Capability Found: cpuid.IBRS'
$pat2='Capability Found: cpuid.IBPB'
$pat3='Capabliity Found: cpuid.STIBP'

$clusterName="EVCCluster" #Your cluster name, script assumes that cluster is available
$cluster= Get-Cluster -Name $clusterName

#Get connected hosts from above cluster
$esxhosts = Get-Cluster $cluster | Get-VMHost -State Connected

#Counter used to give unique name to dummyvm, you can use any number of your choice.

#Iterating through each host for VM creation and scanning vmware.log file
Foreach ($ESXHost in ($esxhosts)){
#Creating dummy vm with below configuration
	New-VM -Name $vm -VMHost $ESXHost -ResourcePool $cluster -DiskGB 1 -MemoryGB 1 -DrsAutomationLevel Disabled -DiskStorageFormat Thin
	Start-VM -VM $vm -RunAsync -Confirm:$false  #DRS may powerON this VM on some other host inside the cluster
	Get-VMLog -VM $vm -Path "C:\"
	if (Get-ChildItem -Path $dest -Filter "*.log" | Where {Get-Content -Path $_.FullName | Select-String -Pattern $pat1}){
 		$row = '' | select HostName, Status
 		$row.HostName = $($ESXHost.name)
 		$report += $row
 		Write-Host "Matched pattern:"+$pat1+":"+$vm+":"+$($ESXHost.name) 
 ElseIf (Get-ChildItem -Path $dest -Filter "*.log" | Where {Get-Content -Path $_.FullName | Select-String -Pattern $pat2}){
  	$row = '' | select HostName, Status
 	$row.HostName = $($ESXHost.name)
	$row.Status ="Patched"
    $report += $row
    Write-Host "Matched pattern:"+$pat2+":"+$vm+":"+$($ESXHost.name) 
  ElseIf (Get-ChildItem -Path $dest -Filter "*.log" | Where {Get-Content -Path $_.FullName | Select-String -Pattern $pat3}){
   	$row = '' | select HostName, Status
  	$row.HostName = $($ESXHost.name)
 	$row.Status ="Patched"
 	$report += $row
   	Write-Host "Matched pattern:"+$pat3+":"+$vm+":"+$($ESXHost.name) 
  	$row = '' | select HostName, Status
 	$row.HostName = $($ESXHost.name)
	$row.Status ="Un-Patched"
  	$report += $row
 	Write-Host "Nothing matched on for VM on host:"$($ESXHost.name) 
 Stop-VM -VM $vm -RunAsync -Confirm:$false
 #you can delete this VM as well to avoid any disk space consumption or minimize the disk size
#Log the report into this CSV file, you can provide your name
$report | Sort HostName | Export-Csv -Path "D:PatchStatus.csv"

#Disconnect the vCenter server
 Disconnect-VIServer -Confirm:$false

Sample CSV file result:
#TYPE Selected.System.String
“VMware vCenter Server 6.5.0 build-7515524″,”Patched”

1. For the sake of simplicity I have hardcoded some values, please do change as per your environment.
2. If you have any comment/feedback on above script, please do provide.
3. There can be other ways to automate the same. Since I started with this approach, I continued. I haven’t yet thought about other approach (probably we may be able to just use datastore browser APIs to navigate/scan vmware.log file instead of downloading it outside).
4. I would recommend you to use this script as sample and make changes as needed. Let me know what changes you did or probably any other way you found.
5. I have tested this script on vCenter/ESXi 6.5 & it worked as expected for me. I will update this article as I update above script

Note: I would like you to understand “vMotion and EVC Information” section from KB, specially below lines. Let me know if you have any doubts I can share my understanding.

“In order to maintain this compatibility the new features are hidden from guests within the cluster until all hosts in the cluster are properly updated”

Some must read links:
1. VC 6.5 U1e release notes
2. VC 6.0 U3d release notes
3. VC 5.5 U3g release notes
4. Microsoft has released similar validation script for their Guest OS

I hope this will be helpful.

4 thoughts on “PowerCLI script : How to confirm a vCenter server, ESXi VMware hypervisor & microcode patches are applied?: Spectre vulnerability

  1. I get this error in the function on 6 out of the 8 temprorary VMs it creates (0 data downloaded on those, data is downloaded on the 2 working).

    Copy-DatastoreItem : 07.03.2018 16:45:56 VimDatastore Download of file ‘https://vc.test.com/folder%2fMyVM51%2fvmware.lo
    g?dcPath=DC%2fProd&dsName=Equalogic-vmware001’ failed. Error message: Response status code does not indicate success: 500 (Internal Server E

    Followed by:
    Copy-DatastoreItem : Object reference not set to an instance of an object.

    All VMs are correctly created and has a vmware.log file in their folders on iSCSI SAN so I don’t know why it would work on one VM and not the next.

Leave a Reply

Your email address will not be published.