VMware ESXi Host Configuration with PowerCLI – (Security Hardening)

By | September 1, 2022

VMware Explore 2022, formerly VMworld, is back to in person attendance in San Francisco!! While it’s not as crowded as years past, it was great to be in person and connect with customers and friends.

My top two goals were to attend everything automation and security related. While walking out of a ‘Ransomware Prevention’ session, I ran into my good friend Nathan from Binary Fu, and we started talking about things covered from the session

I shared with Nathan that Ansible allows me to easily apply the VMware Security Hardening Best Practices to an ESXi host and that I plan on adding some additional steps learned from the Ransomware session. 

While Ansible has been awesome, not every environment allows me to deploy Ansible or use my laptop to run playbooks and Nathan suggested converting my Ansible playbooks to PowerCLI for use in those environments.

I haven’t spent much time with PowerShell and Nathan offered to help convert my Ansible playbooks into PowerShell and I decided turn this into a collaboration with Nathan on Binary Fu’s first blog post.

Please be aware this is not a prescription to keep you from being hacked, but rather an improvement of your security posture specific to vSphere.

The vSphere Security Configuration Guide (SCG) 7 is the baseline for security hardening of VMware vSphere itself, and the core of VMware security best practices. The VMware vSphere Security Hardening Guide gives recommended guidance for vSphere Administrators looking to protect their infrastructure.

Please refer to my original post on how I implemented these best practices into an Ansible playbook. Ansible Security Hardening Playbook

Configure Security Best Practices – PowerCLI

ESXi MANAGE SERVICES

#====================================================================================================================
    Connect-VIServer -Server $_.mgmtip -User $hostuser -Password $hostpass

Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'sfcbd-watchdog'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'sfcbd-watchdog'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'slpd'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'slpd'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'snmpd'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'snmpd'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM-SSH'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM-SSH'} | Stop-VMHostService -Confirm:$false

ESXi Scratch syslog Configuration Tasks

# Scratch Settings
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name ScratchConfig.ConfiguredScratchLocation | Set-AdvancedSetting -Value '/vmfs/volumes/logs/$_.hostname' -Confirm:$false

ESXi DNS / NTP Configuration Tasks

 # AD Domain Settings
Get-VMHostAuthentication | Set-VMHostAuthentication -Domain $_.domain -User $_.aduser -Password $_.adpass -JoinDomain
Get-VMHostNetwork -VMHost $_.mgmtip | Set-VMHostNetwork -DomainName $_.domain -SearchDomain $_.domain -DnsAddress $_.dns1,$_.dns2
    Add-VmHostNtpServer -NtpServer $_.ntp1
    Add-VmHostNtpServer -NtpServer $_.ntp2
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq "ntpd"} | Set-VMHostService -Policy On
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq "ntpd"} | Restart-VMHostService -Confirm:$false

ESXi Security Configuration Tasks

# Advanced Settings
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Config.HostAgent.log.level | Set-AdvancedSetting -Value info -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Config.HostAgent.plugins.solo.enableMob | Set-AdvancedSetting -Value False -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Mem.ShareForceSalting | Set-AdvancedSetting -Value 2 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.AccountLockFailures | Set-AdvancedSetting -Value 5 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.AccountUnlockTime | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.PasswordHistory | Set-AdvancedSetting -Value 5 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.PasswordQulityControl | Set-AdvancedSetting -Value "similar=deny retry=3 min=disabled,disabled,disabled,disabled,15" -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.DcuiTimeOut | Set-AdvancedSetting -Value 600 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiShellInteractiveTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiShellTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiVPsDisabledProtocols | Set-AdvancedSetting -Value "sslv3,tlsv1,tlsv1.1" -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.SuppressShellWarning | Set-AdvancedSetting -Value 1 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name VMkernel.Boot.execInstalledOnly | Set-AdvancedSetting -Value True -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Mem.ShareForceSalting | Set-AdvancedSetting -Value 0 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Misc.BlueScreenTimeout | Set-AdvancedSetting -Value 60 -Confirm:$false

Combined PowerShell script

All the above snippets together form the PowerSell script to help enforce the VMware ESXi Security Configurations, hardening and other common configurations. I will included an excel csv file that I will be expanding on in another blog post.

#========================================================================================================================
#
# Specify host credentials
#
#========================================================================================================================
$hostuser = 'root'
$hostpass = 'Explore2022!'
$vmhosts = Import-CSV -Path path_to_file_with_variables.csv
Get-Variable -Name $_.mgmtip
$vmhosts| ForEach {$vmhosts.hostname} {
    #====================================================================================================================
	#
	# Connect to each host
	#
	#====================================================================================================================
    Connect-VIServer -Server $_.mgmtip -User $hostuser -Password $hostpass
	
	#====================================================================================================================
	#
	# vSphere Security Best Practices
	#
	#====================================================================================================================
Write-host Configuring vSphere Security Best Practices -ForegroundColor Yellow

# AD Domain Settings
Get-VMHostAuthentication | Set-VMHostAuthentication -Domain $_.domain -User $_.aduser -Password $_.adpass -JoinDomain
Get-VMHostNetwork -VMHost $_.mgmtip | Set-VMHostNetwork -DomainName $_.domain -SearchDomain $_.domain -DnsAddress $_.dns1,$_.dns2
    Add-VmHostNtpServer -NtpServer $_.ntp1
    Add-VmHostNtpServer -NtpServer $_.ntp2
    
# Advanced Settings
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Config.HostAgent.log.level | Set-AdvancedSetting -Value info -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Config.HostAgent.plugins.solo.enableMob | Set-AdvancedSetting -Value False -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Mem.ShareForceSalting | Set-AdvancedSetting -Value 2 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.AccountLockFailures | Set-AdvancedSetting -Value 5 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.AccountUnlockTime | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.PasswordHistory | Set-AdvancedSetting -Value 5 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Security.PasswordQulityControl | Set-AdvancedSetting -Value "similar=deny retry=3 min=disabled,disabled,disabled,disabled,15" -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.DcuiTimeOut | Set-AdvancedSetting -Value 600 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiShellInteractiveTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiShellTimeOut | Set-AdvancedSetting -Value 900 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.ESXiVPsDisabledProtocols | Set-AdvancedSetting -Value "sslv3,tlsv1,tlsv1.1" -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name UserVars.SuppressShellWarning | Set-AdvancedSetting -Value 1 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name VMkernel.Boot.execInstalledOnly | Set-AdvancedSetting -Value True -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Mem.ShareForceSalting | Set-AdvancedSetting -Value 0 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Misc.BlueScreenTimeout | Set-AdvancedSetting -Value 60 -Confirm:$false

# Network Settings
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Net.BlockGuestBPDU | Set-AdvancedSetting -Value 1 -Confirm:$false
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name Net.DVFilterBindIpAddress | Set-AdvancedSetting -Value "" -Confirm:$false
Get-VirtualSwitch | Get-SecurityPolicy | Set-SecurityPolicy -ForgedTransmits $false 
Get-VirtualPortGroup | Get-SecurityPolicy | Set-SecurityPolicy -ForgedTransmitsInherited $true
Get-VirtualSwitch | Get-SecurityPolicy | Set-SecurityPolicy -MacChanges $false
Get-VirtualPortGroup | Get-SecurityPolicy | Set-SecurityPolicy -MacChangesInherited $true
Get-VirtualSwitch | Get-SecurityPolicy | Set-SecurityPolicy -AllowPromiscuous $false
Get-VirtualPortGroup | Get-SecurityPolicy | Set-SecurityPolicy -AllowPromiscuousInherited $true

# Scratch Settings
Get-AdvancedSetting -Entity (Get-VMHost -Name $_.mgmtip) -Name ScratchConfig.ConfiguredScratchLocation | Set-AdvancedSetting -Value '/vmfs/volumes/logs/$_.hostname' -Confirm:$false

# Service Settings
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq "ntpd"} | Set-VMHostService -Policy On
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq "ntpd"} | Restart-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'sfcbd-watchdog'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'sfcbd-watchdog'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'slpd'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'slpd'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'snmpd'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'snmpd'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM'} | Stop-VMHostService -Confirm:$false
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM-SSH'} | Set-VMHostService -Policy Off
Get-VMHostService -Server $_.mgmtip | ?{$_.Key -eq 'TSM-SSH'} | Stop-VMHostService -Confirm:$false
            
    #====================================================================================================================
	#
	# Disconnect from each host
	#
	#====================================================================================================================
	Disconnect-VIServer $_.mgmtip -Confirm:$false
}

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.