So i took some time and wrote the beginnings of a hardening checkout script for both hosts and guests. While not every item in the 5.0 hardening guide is listed, i think the main ones are covered and it is a good starting point for anyone who doesn't already have a checkout script of their own. I have attached the files as well as pasted the code here. You will need to supply a vCenter list as a text file (it assumes you have more than one vCenter) as well as a root credentials (i use a powershell encrypted password text file but you can adjust that to plain text if you dont mind having a root password as plain text in your environment)
Host Check:
function Get-VMAdvancedConfiguration {
<#
.SYNOPSIS
Lists advanced configuration setting (VMX Setting) for a VM
or multiple VMs
.DESCRIPTION
The function will list a VMX setting for a VM
or multiple VMs
.PARAMETER VM
A virtual machine or multiple virtual machines
.EXAMPLE 1
PS> Get-VM MyVM1 | Get-VMAdvancedConfiguration
#>
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
$vm,
[String]$key
)
process{
if ($key) {
$VM | Foreach {
$_.ExtensionData.Config.ExtraConfig | Select * -ExcludeProperty DynamicType, DynamicProperty | Where { $_.Key -eq $key }
}
} Else {
$VM | Foreach {
$_.ExtensionData.Config.ExtraConfig | Select * -ExcludeProperty DynamicType, DynamicProperty
}
}
}
}
$vclist = Get-Content "vCenterList.txt"
$pass = cat securerootpwd.txt | ConvertTo-SecureString
$rcred = new-object -typename System.Management.Automation.PSCredential -argumentlist "root",$pass
$HostData = @()
foreach($vc in $vclist)
{
Connect-VIServer $vc
$vmhs = Get-VMHost
Disconnect-VIServer -Server * -Confirm:$false
foreach($vmh in $vmhs)
{
$myItem = "" | Select VC , Host , Err , Version , Acc1 , Com2 , Com3 , Com8 , Con1 , Con2 , Con3 , Con4 , Con5 , Log2
$myItem.Host = $vmh.Name
$myItem.VC = $vc
$myItem.Version = $vmh.Version
Connect-VIServer $vmh.Name -Credential $rcred
$dom = Get-VMHost | Get-VMHostAuthentication | Select VmHost, Domain, DomainMembershipStatus
if($dom.DomainMembershipStatus -ne "OK")
{
$myItem.Acc1 = "Fail enable-ad-auth"
}
else
{
$myItem.Acc1 = "Pass enable-ad-auth"
}
$ntp = Get-VMHost | Select Name, @{N="NTPSetting";E={$_ | Get-VMHostNtpServer}}
if($ntp.NTPSetting -ne $null)
{
$myItem.Com2 = "Pass config-ntp"
}
else
{
$myItem.Com2 = "Fail config-ntp"
}
$snmp = Get-VMHostSnmp
if($snmp -eq $null)
{
$myItem.Com3 = "Fail config-snmp"
}
else
{
$myItem.Com3 = "Fail config-snmp"
}
$dvfilt = Get-VMHost | Select Name, @{N="Net.DVFilterBindIpAddress";E={$_ | Get-VMHostAdvancedConfiguration Net.DVFilterBindIpAddress | Select -ExpandProperty Values}}
if($dvfilt.Net.DVFilterBindIpAddress.Length -eq $null)
{
$myItem.Com8 = "Pass verify-dvfilter-bind"
}
else
{
$myItem.Com8 = "Fail verify-dvfilter-bind"
}
$dcui = Get-VMHost | Get-VMHostService | Where { $_.key -eq "DCUI" }
if($dcui.Policy -eq "off")
{
$myItem.Con1 = "Pass disable-dcui"
}
else
{
$myItem.Con1 = "Fail disable-dcui"
}
$shell = Get-VMHost | Get-VMHostService | Where { $_.key -eq "TSM" } | Select VMHost, Key, Label, Policy, Running, Required
if($shell.Policy -eq "off")
{
$myItem.Con2 = "Pass disable-esxi-shell"
}
else
{
$myItem.Con2 = "Fail disable-esxi-shell"
}
$ssh = Get-VMHost | Get-VMHostService | Where { $_.key -eq "TSM-SSH" } | Select VMHost, Key, Label, Policy, Running, Required
if($ssh.Policy -eq "off")
{
$myItem.Con3 = "Pass disable-ssh"
}
else
{
$myItem.Con3 = "Fail disable-ssh"
}
$ld = Get-VMHost | Select Name,@{N="Lockdown";E={$_.Extensiondata.Config.adminDisabled}}
if($ld.Lockdown -eq $null)
{
$myItem.Con4 = "Fail enable-lockdown-mode"
}
else
{
$myItem.Con4 = "Pass enable-lockdown-mode"
}
$cim = Get-VMHostAccount
if($cim.Count -lt 15)
{
$myItem.Con5 = "Pass limit-cim-access"
}
else
{
$myItem.Con5 = "Fail limit-cim-access"
}
$remlog = Get-VMHostSysLogServer
if($remlog -ne $null)
{
$myItem.Log2 = "Pass enable-remote-syslog"
}
else
{
$myItem.Log2 = "Fail enable-remote-syslog"
}
Disconnect-VIServer -Server * -Confirm:$false
$HostData += $myItem
}
}
$file = "c:\harden\hosthardenreport.csv"
$HostData | ConvertTo-Csv | Out-File $file
VM Guest Check:
function Get-VMAdvancedConfiguration {
<#
.SYNOPSIS
Lists advanced configuration setting (VMX Setting) for a VM
or multiple VMs
.DESCRIPTION
The function will list a VMX setting for a VM
or multiple VMs
.PARAMETER VM
A virtual machine or multiple virtual machines
.EXAMPLE 1
PS> Get-VM MyVM1 | Get-VMAdvancedConfiguration
#>
param(
[Parameter(Mandatory=$true,ValueFromPipeline=$true)]
$vm,
[String]$key
)
process{
if ($key) {
$VM | Foreach {
$_.ExtensionData.Config.ExtraConfig | Select * -ExcludeProperty DynamicType, DynamicProperty | Where { $_.Key -eq $key }
}
} Else {
$VM | Foreach {
$_.ExtensionData.Config.ExtraConfig | Select * -ExcludeProperty DynamicType, DynamicProperty
}
}
}
}
Function Get-ParallelPort {
Param (
[Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
$VM
)
Process {
Foreach ($VMachine in $VM) {
Foreach ($Device in $VMachine.ExtensionData.Config.Hardware.Device) {
If ($Device.gettype().Name -eq "VirtualParallelPort"){
$Details = New-Object PsObject
$Details | Add-Member Noteproperty VM -Value $VMachine
$Details | Add-Member Noteproperty Name -Value $Device.DeviceInfo.Label
If ($Device.Backing.FileName) { $Details | Add-Member Noteproperty Filename -Value $Device.Backing.FileName }
If ($Device.Backing.Datastore) { $Details | Add-Member Noteproperty Datastore -Value $Device.Backing.Datastore }
If ($Device.Backing.DeviceName) { $Details | Add-Member Noteproperty DeviceName -Value $Device.Backing.DeviceName }
$Details | Add-Member Noteproperty Connected -Value $Device.Connectable.Connected
$Details | Add-Member Noteproperty StartConnected -Value $Device.Connectable.StartConnected
$Details
}
}
}
}
}
Function Get-SerialPort {
Param (
[Parameter(Mandatory=$True,ValueFromPipeline=$True,ValueFromPipelinebyPropertyName=$True)]
$VM
)
Process {
Foreach ($VMachine in $VM) {
Foreach ($Device in $VMachine.ExtensionData.Config.Hardware.Device) {
If ($Device.gettype().Name -eq "VirtualSerialPort"){
$Details = New-Object PsObject
$Details | Add-Member Noteproperty VM -Value $VMachine
$Details | Add-Member Noteproperty Name -Value $Device.DeviceInfo.Label
If ($Device.Backing.FileName) { $Details | Add-Member Noteproperty Filename -Value $Device.Backing.FileName }
If ($Device.Backing.Datastore) { $Details | Add-Member Noteproperty Datastore -Value $Device.Backing.Datastore }
If ($Device.Backing.DeviceName) { $Details | Add-Member Noteproperty DeviceName -Value $Device.Backing.DeviceName }
$Details | Add-Member Noteproperty Connected -Value $Device.Connectable.Connected
$Details | Add-Member Noteproperty StartConnected -Value $Device.Connectable.StartConnected
$Details
}
}
}
}
}
$data = @()
$vclist = Get-Content "vCenterList.txt"
foreach($vc in $vclist)
{
Connect-VIServer $vc
$vms = Get-VM
foreach($vm in $vms)
{
$myItem = "" | Select vc , name , hw , tools , com1 , com4 , dev1 , dev2 , dev3 , dev4 , dev5 , dev6 , dev7 , mon1 , mon2 , mon3 , mon4 , mon5 , mon6 , mon7 , mon8 , mon9 , mon10 , mon11 , mon12 , mon13 , mon14 , mon15 , mon16 , mon17 , mon18 , mon19 , mon20 , mon21 , mon22 , mon23 , mon24 , mon25 , mon26 , mon27 , mon28 , tool1 , tool4 , tool5 , tool6
$myItem.Name = $vm.Name
$myItem.vc = $vc
$myItem.hw = $vm.Version
$myItem.tools = $vm.Guest.ExtensionData.ToolsStatus
$com1 = $vm | Select Name, @{N="Setting";E={($ | Get-VMAdvancedConfiguration -key "vmci0.unrestricted").Value }}
if(!$com.Setting)
{
$myItem.com1 = "Pass disable-intervm-vmci"
}
else
{
$myItem.com1 = "Fail disable-intervm-vmci"
}
$com4 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "tools.setInfo.sizeLimit").Value }}
if($com4.Setting -lt 1048576)
{
$myItem.com4 = "Fail limit-setinfo-size"
}
else
{
$myItem.com4 = "Pass limit-setinfo-size"
}
$dev1 = $vm | Get-FloppyDrive | Select Parent, Name, ConnectionState
if(!$dev1)
{
$myItem.dev1 = "Passed disconnect-devices-floppy"
}
else
{
$myItem.dev1 = "Failed disconnect-devices-floppy"
}
$dev2 = $vm | Get-CDDrive
if(!$dev2)
{
$myItem.dev2 = "Passed disconnect-devices-ide"
}
else
{
$myItem.dev2 = "Failed disconnect-devices-ide"
}
$dev3 = $vm | Get-ParallelPort
if(!$dev3)
{
$myItem.dev3 = "Passed disconnect-devices-parallel"
}
else
{
$myItem.dev3 = "Failed disconnect-devices-parallel"
}
$dev4 = $vm | Get-SerialPort
if(!$dev4)
{
$myItem.dev4 = "Passed disconnect-devices-serial"
}
else
{
$myItem.dev4 = "Failed disconnect-devices-serial"
}
$dev5 = $vm | Get-USBDevice
if(!$dev5)
{
$myItem.dev5 = "Passed disconnect-devices-usb"
}
else
{
$myItem.dev5 = "Failed disconnect-devices-usb"
}
$dev6 = $vm | Select Name, @{N="Setting";E={($_ | Get-AdvancedConfiguration -key "isolation.device.connectable.disable").Value }}
if($dev6.Setting)
{
$myItem.dev6 = "Passed prevent-device-interaction-connect"
}
else
{
$myItem.dev6 = "Failed prevent-device-interaction-connect"
}
$dev7 = $vm | Select Name, @{N="Setting";E={($_ | Get-AdvancedConfiguration -key "isolation.device.edit.disable").Value }}
if($dev7.Setting)
{
$myItem.dev7 = "Passed prevent-device-interaction-edit"
}
else
{
$myItem.dev7 = "Failed prevent-device-interaction-edit"
}
$mon1 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.copy.disable").Value }}
if($mon1.Setting)
{
$myItem.mon1 = "Passed disable-console-copy"
}
else
{
$myItem.mon1 = "Failed disable-console-copy"
}
$mon2 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.dnd.disable").Value }}
if(!$mon2.Setting)
{
$myItem.mon2 = "Passed disable-console-dnd"
}
else
{
$myItem.mon2 = "Failed disable-console-dnd"
}
$mon3 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.setGUIOptions.enable").Value }}
if(!$mon3.Setting)
{
$myItem.mon3 = "Passed disable-console-gui-options"
}
else
{
$myItem.mon3 = "Failed disable-console-gui-options"
}
$mon4 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.paste.disable").Value }}
if($mon4.Setting)
{
$myItem.mon4 = "Passed disable-console-paste"
}
else
{
$myItem.mon4 = "Failed disable-console-paste"
}
$mon5 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.hgfsServerSet.disable").Value }}
if($mon5.Setting)
{
$myItem.mon5 = "Passed disable-hgfs"
}
else
{
$myItem.mon5 = "Failed disable-hgfs"
}
$mon6 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.monitor.control.disable").Value }}
if($mon6.Setting)
{
$myItem.mon6 = "Passed disable-monitor-control"
}
else
{
$myItem.mon6 = "Failed disable-monitor-control"
}
$mon7 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.ghi.autologon.disable").Value }}
if($mon7.Setting)
{
$myItem.mon7 = "Passed disable-unexposed-features-autologon"
}
else
{
$myItem.mon7 = "Failed disable-unexposed-features-autologon"
}
$mon8 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.bios.bbs.disable").Value }}
if($mon8.Setting)
{
$myItem.mon8 = "Passed disable-unexposed-features-biosbbs"
}
else
{
$myItem.mon8 = "Failed disable-unexposed-features-biosbbs"
}
$mon9 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.getCreds.disable").Value }}
if($mon9.Setting)
{
$myItem.mon9 = "Passed disable-unexposed-features-getcreds"
}
else
{
$myItem.mon9 = "Failed disable-unexposed-features-getcreds"
}
$mon10 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.ghi.launchmenu.change").Value }}
if($mon10.Setting)
{
$myItem.mon10 = "Passed disable-unexposed-features-launchmenu"
}
else
{
$myItem.mon10 = "Failed disable-unexposed-features-launchmenu"
}
$mon11 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.memSchedFakeSampleStats.disable").Value }}
if($mon11.Setting)
{
$myItem.mon11 = "Passed disable-unexposed-features-memsfss"
}
else
{
$myItem.mon11 = "Failed disable-unexposed-features-memsfss"
}
$mon12 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.ghi.protocolhandler.info.disable").Value }}
if($mon12.Setting)
{
$myItem.mon12 = "Passed disable-unexposed-features-protocolhandler"
}
else
{
$myItem.mon12 = "Failed disable-unexposed-features-protocolhandler"
}
$mon13 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.ghi.host.shellAction.disable").Value }}
if($mon13.Setting)
{
$myItem.mon13 = "Passed disable-unexposed-features-shellaction"
}
else
{
$myItem.mon13 = "Failed disable-unexposed-features-shellaction"
}
$mon14 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.dispTopoRequest.disable").Value }}
if($mon14.Setting)
{
$myItem.mon14 = "Passed disable-unexposed-features-toporequest"
}
else
{
$myItem.mon14 = "Failed disable-unexposed-features-toporequest"
}
$mon15 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.trashFolderState.disable").Value }}
if($mon15.Setting)
{
$myItem.mon15 = "Passed disable-unexposed-features-trashfolderstate"
}
else
{
$myItem.mon15 = "Failed disable-unexposed-features-trashfolderstate"
}
$mon16 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.ghi.trayicon.disable").Value }}
if($mon16.Setting)
{
$myItem.mon16 = "Passed disable-unexposed-features-trayicon"
}
else
{
$myItem.mon16 = "Failed disable-unexposed-features-trayicon"
}
$mon17 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unity.disable").Value }}
if($mon17.Setting)
{
$myItem.mon17 = "Passed disable-unexposed-features-unity"
}
else
{
$myItem.mon17 = "Failed disable-unexposed-features-unity"
}
$mon18 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unityInterlockOperation.disable").Value }}
if($mon18.Setting)
{
$myItem.mon18 = "Passed disable-unexposed-features-unity-interlock"
}
else
{
$myItem.mon18 = "Failed disable-unexposed-features-unity-interlock"
}
$mon19 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unity.push.update.disable").Value }}
if($mon19.Setting)
{
$myItem.mon19 = "Passed disable-unexposed-features-unitypush"
}
else
{
$myItem.mon19 = "Failed disable-unexposed-features-unitypush"
}
$mon20 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unity.taskbar.disable").Value }}
if($mon20.Setting)
{
$myItem.mon20 = "Passed disable-unexposed-features-unity-taskbar"
}
else
{
$myItem.mon20 = "Failed disable-unexposed-features-unity-taskbar"
}
$mon21 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unityActive.disable").Value }}
if($mon21.Setting)
{
$myItem.mon21 = "Passed disable-unexposed-features-unity-unityactive"
}
else
{
$myItem.mon21 = "Failed disable-unexposed-features-unity-unityactive"
}
$mon22 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.unity.windowContents.disable").Value }}
if($mon22.Setting)
{
$myItem.mon22 = "Passed disable-unexposed-features-unity-windowcontents"
}
else
{
$myItem.mon22 = "Failed disable-unexposed-features-unity-windowcontents"
}
$mon23 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.vmxDnDVersionGet.disable").Value }}
if($mon23.Setting)
{
$myItem.mon23 = "Passed disable-unexposed-features-versionget"
}
else
{
$myItem.mon23 = "Failed disable-unexposed-features-versionget"
}
$mon24 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.guestDnDVersionSet.disable").Value }}
if($mon24.Setting)
{
$myItem.mon24 = "Passed disable-unexposed-features-versionset"
}
else
{
$myItem.mon24 = "Failed disable-unexposed-features-versionset"
}
$mon25 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "ethernetn.filtern.name*").Value }}
if(!$mon25.Setting)
{
$myItem.mon25 = "Passed verify-network-filter"
}
else
{
$myItem.mon25 = "Failed verify-network-filter"
}
$mon26 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "vmsafe.agentAddress").Value }}
if(!$mon26.Setting)
{
$myItem.mon26 = "Passed verify-vmsafe-cpumem-agentaddress"
}
else
{
$myItem.mon26 = "Failed verify-vmsafe-cpumem-agentaddress"
}
$mon27 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "vmsafe.agentPort").Value }}
if(!$mon27.Setting)
{
$myItem.mon27 = "Passed verify-vmsafe-cpumem-agentport"
}
else
{
$myItem.mon27 = "Failed verify-vmsafe-cpumem-agentport"
}
$mon28 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "vmsafe.enable").Value }}
if(!$mon28.Setting)
{
$myItem.mon28 = "Passed verify-vmsafe-cpumem-enable"
}
else
{
$myItem.mon28 = "Failed verify-vmsafe-cpumem-enable"
}
$tool1 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "isolation.tools.autoInstall.disable").Value }}
if($tool1.Setting)
{
$myItem.tool1 = "Passed disable-autoinstall"
}
else
{
$myItem.tool1 = "Failed disable-autoinstall"
}
$tool4 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "log.keepOld").Value }}
if($tool4.Setting -eq 10)
{
$myItem.tool4 = "Passed limit-log-number"
}
else
{
$myItem.tool4 = "Failed limit-log-number"
}
$tool5 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "log.rotateSize").Value }}
if($tool5.Setting -le 100000)
{
$myItem.tool5 = "Passed limit-log-size"
}
else
{
$myItem.tool5 = "Failed limit-log-size"
}
$tool6 = $vm | Select Name, @{N="Setting";E={($_ | Get-VMAdvancedConfiguration -key "tools.guestlib.enableHostInfo").Value }}
if(!$tool6.Setting)
{
$myItem.tool6 = "Passed restrict-host-info"
}
else
{
$myItem.tool6 = "Failed restrict-host-info"
}
$data += $myItem
}
Disconnect-VIServer -Confirm:$false
}
$file = "c:\harden\vmguesthardenreport.csv"
$data | ConvertTo-Csv | Out-File $file
It might be a good idea to export the settings to a CSV file for editting, and then have the script apply the settings in the file, and generate the reports, etc... That gives the script a little more life and usability.
Please consider me as a beginner and please explain how to use this:smileyconfused:. How do I provide the list VM list and the root credentials.
Thank you very much would be a big help.
So here is the part where the credentials are created for use:
$pass = cat securerootpwd.txt | ConvertTo-SecureString
$rcred = new-object -typename System.Management.Automation.PSCredential -argumentlist "root",$pass
securerrotpwd.txt is created like this:
Read-Host -AsSecureString | ConvertFrom-SecureString | Out-File PATHTO\securerootpwd.txt
As for the list, its just a simple text file with a vCenter name per line:
$vclist = Get-Content "PATHTO\vCenterList.txt"
It then loops through each vCenter in your list:
foreach($vc in $vclist)
{
Connect-VIServer $vc -Credential $rcred
#here is where teh VMs are gathered
$vms = Get-VM
foreach($vm in $vms)
{....
Hope that helps.