Kürzlich habe ich einen Beitrag zum härten der vSphere VM Konfigurationen veröffentlicht (Projekt nun auch auf GitHub), etwas Komplexer gestaltet sich das Thema ESXi Hardening mit PowerCLI.
Hier sind wesentlich mehr Aspekte zu beachten. Auch der VMware Security Hardening Guide für vSphere 5.5 Update 1 (Download) gibt nicht so viel her wie für VMs.
Grundlegend ist aber meines Erachtens nach für das ESXi Hardening folgendes zu tun:
- Nur benötigte Dienste starten
- Wenn eingehende Ports offen sind, diese per Firewall einschränken
- Wenn SSH benötigt wird, Timeouts festlegen
- Logging und Zeitsynchronisation aktivieren
Ich habe mir hierfür wieder ein PowerCLI Script erstellt. Allerdings, wegen den umfangreichen Parametern, mit einer XML als Eingabe.
Dieses Script ist noch in der Entwicklung und bisher nicht mit allen gewünschten Aktionen versehen.
Wer sich an der Weiterentwickelung beteiligen möchte, ist gerne eingeladen (GitHub Projekt).
ESXi Hardening mit PowerCLI – Komponenten
ESXi Hardening – XML Eingabe
<?xml version="1.0" encoding="utf-8"?> <Config version="2.0"> <Variable Name="SNMP_NET" Value="192.168.0.0/16" /> <Variable Name="MGMT_NET" Value="192.168.0.0/16" /> <NTP> <First>192.168.130.1</First> <Second>192.168.130.2</Second> </NTP> <SSH> <Enabled>True</Enabled> <Timeout>900</Timeout> </SSH> <Syslog> <Enabled>True</Enabled> <Server>udp://192.168.130.10:514</Server> </Syslog> </Config>
ESXi Hardening -PowerCLI Script
############################################################################# # ESXi Hardening Script # Written by Markus Kraus # Version 1.1, 02.2016 # # http://mycloudrevolution.com/ # # Changelog: # 2016.01 ver 1.0 Base Release # 2016.02 ver 1.1 # # ############################################################################## ## Preparation # Load Snapin (if not already loaded) if (!(Get-PSSnapin -name VMware.VimAutomation.Core -ErrorAction:SilentlyContinue)) { if (!(Add-PSSnapin -PassThru VMware.VimAutomation.Core)) { # Error out if loading fails write-host "`nFATAL ERROR: Cannot load the VIMAutomation Core Snapin. Is the PowerCLI installed?`n" exit } } ## Global $mgmtServices = @("sshClient","webAccess") $MenueForegroundcolor = "Black" ## Inputs # Menue Write-Host `n"ESXi Hardening Module" -ForeGroundColor $MenueForegroundcolor Write-Host `n"Type 'q' or hit enter to drop to shell"`n Write-Host -NoNewLine "<" -foregroundcolor $MenueForegroundcolor Write-Host -NoNewLine "ESXi or vCenter Connection?" Write-Host -NoNewLine ">" -foregroundcolor $MenueForegroundcolor Write-Host -NoNewLine "[" Write-Host -NoNewLine "A" -foregroundcolor $MenueForegroundcolor Write-Host -NoNewLine "]" Write-Host -NoNewLine `t`n "A1 - " -foregroundcolor $MenueForegroundcolor Write-host -NoNewLine "vCenter" Write-Host -NoNewLine `t`n "A2 - " -foregroundcolor $MenueForegroundcolor Write-host -NoNewLine "ESXi" $sel = Read-Host "Which option?" # Connections [System.Reflection.Assembly]::LoadWithPartialName('Microsoft.VisualBasic') | Out-Null Switch ($sel) { "A1" { $vCenter = [Microsoft.VisualBasic.Interaction]::InputBox("vCenter Host FQDN or IP", "Host", "vCenter.test.lab") $HostExclude = [Microsoft.VisualBasic.Interaction]::InputBox("ESXi Hosts to exclude", "WildCard", "esx01|esx02") # Start vCenter Connection Write-Host "`nStarting to Process vCenter Connection to " $vCenter " ..."-ForegroundColor Magenta $OpenConnection = $global:DefaultVIServers | where { $_.Name -eq $vCenter } if($OpenConnection.IsConnected) { Write-Host "`nvCenter is Already Connected..." -ForegroundColor Blue $VIConnection = $OpenConnection } else { Write-Host "`nConnecting vCenter..." $VIConnection = Connect-VIServer -Server $vCenter } if (-not $VIConnection.IsConnected) { Write-Error "`nError: vCenter Connection Failed" Exit } # End vCenter Connection $ESXiHostList = Get-VMHost | Where-Object {$_.Name -notmatch $HostExclude} } "A2" { $ESXiHost = [Microsoft.VisualBasic.Interaction]::InputBox("ESXi Host FQDN or IP", "Host", "esx01.test.lab") # Start ESXi Connection Write-Host "`nStarting to Process ESXi Connection to " $ESXiHost " ..."-ForegroundColor Magenta $OpenConnection = $global:DefaultVIServers | where { $_.Name -eq $ESXiHost } if($OpenConnection.IsConnected) { Write-Host "`nESXi is Already Connected..." -ForegroundColor Blue $VIConnection = $OpenConnection } else { Write-Host "`nConnecting ESXi..." $VIConnection = Connect-VIServer -Server $ESXiHost } if (-not $VIConnection.IsConnected) { Write-Error "`nError: ESXi Connection Failed" Exit } # End ESXi Connection $ESXiHostList = Get-VMHost } {($_ -like "*q*") -or ($_ -eq "")} { Write-Host "`nNo input or 'q' seen... dropping to shell" -foregroundColor $foregroundColor Exit } } If (($ESXiHostList).Count -lt 1) { Write-Error "`nError: No Hosts to Process... Exiting" Exit } # Read XML $Validate = $true If (Test-Path ".\Config.xml") { try {$Variable = [XML] (Get-Content ".\Config.xml")} catch {$Validate = $false;Write-Host "Invalid Config.xml" -ForegroundColor Red} } Else { $Validate = $false Write-Host "Missing Config.xml" -ForegroundColor Red Exit } If ($Validate) { Write-Host "Reading XML Inputs:" -ForegroundColor Green $NTP1 = $Variable.Config.NTP.First $NTP2 = $Variable.Config.NTP.Second Write-Host "NTP List: $NTP1, $NTP2" -ForegroundColor DarkGray $SSHenaled = $Variable.Config.SSH.Enabled Write-Host "Enabling SSH: $SSHenaled" -ForegroundColor DarkGray $SSHTimeout = $Variable.Config.SSH.Timeout Write-Host "SSH Tmeout: $SSHTimeout" -ForegroundColor DarkGray $SyslogEnaled = $Variable.Config.Syslog.Enabled Write-Host "Enabling Syslog: $SyslogEnaled" -ForegroundColor DarkGray $SyslogServer = $Variable.Config.Syslog.Server Write-Host "Syslog Server: $SyslogServer" -ForegroundColor DarkGray $SNMP_NET = ($Variable.Config.Variable | Where-Object {$_.Name -eq "SNMP_NET"}).Value Write-Host "Firewall SNMP Network: $SNMP_NET" -ForegroundColor DarkGray $MGMT_NET = ($Variable.Config.Variable | Where-Object {$_.Name -eq "MGMT_NET"}).Value Write-Host "Firewall MGMT Network (SSH, vSphere Client): $MGMT_NET" -ForegroundColor DarkGray } ## Execute foreach ($ESXiHost in $ESXiHostList){ # Configure NTP Write-Host "NTP Configuration on $ESXiHost started..." -ForegroundColor Green $ESXiHost | Add-vmhostntpserver -ntpserver $NTP1 -confirm:$False -ErrorAction SilentlyContinue $ESXiHost | Add-vmhostntpserver -ntpserver $NTP2 -confirm:$False -ErrorAction SilentlyContinue $ntpservice = $ESXiHost | get-vmhostservice | Where-Object {$_.key -eq "ntpd"} Set-vmhostservice -HostService $ntpservice -Policy "on" -confirm:$False | Out-Null $hosttimesystem = get-view $ESXiHost.ExtensionData.ConfigManager.DateTimeSystem $hosttimesystem.UpdateDateTime([DateTime]::UtcNow) start-vmhostservice -HostService $ntpservice -confirm:$False | Out-Null Write-Host "NTP Configuration on $ESXiHost finished..." -ForegroundColor Green # Report Services with Enabled Incomming Port Exceptions Write-Host "Services on $ESXiHost with Enabled Incomming Port Exceptions:" -ForegroundColor Green $ESXiHost| Get-VMHostFirewallException | where {$_.Enabled -eq "True" -and $_.IncomingPorts -ne ""} | Out-Default $esxcli = Get-EsxCli -VMHost $ESXiHost # SNMP Try { Write-Host "Configuring Firewall SNMP Strict Exception on $ESXiHost started..." -ForegroundColor Green $esxcli.network.firewall.ruleset.set($false,$true,'snmp') } Catch { Switch -Wildcard ($_.Exception) { "*Already use allowed ip list*" {Write-Host "...Already use allowed ip list" -ForegroundColor Blue} Default { Write-Host $_.Exception -ForegroundColor Red} } } Try { Write-Host "Configuring Firewall SNMP IP Exception on $ESXiHost started..." -ForegroundColor Green $esxcli.network.firewall.ruleset.allowedip.add($SNMP_NET,'snmp') } Catch { Switch -Wildcard ($_.Exception) { "*Ip address already exist*" {Write-Host "...Ip address already exist" -ForegroundColor Blue} Default { Write-Host $_.Exception -ForegroundColor Red} } } # mgmtServices foreach ($mgmtService in $mgmtServices){ Try { Write-Host "Configuring Firewall $mgmtService Strict Exception on $ESXiHost started..." -ForegroundColor Green $esxcli.network.firewall.ruleset.set($false,$true,$mgmtService) } Catch { Switch -Wildcard ($_.Exception) { "*Already use allowed ip list*" {Write-Host "...Already use allowed ip list" -ForegroundColor Blue} Default { Write-Host $_.Exception -ForegroundColor Red} } } Try { Write-Host "Configuring Firewall $mgmtService IP Exception on $ESXiHost started..." -ForegroundColor Green $esxcli.network.firewall.ruleset.allowedip.add($MGMT_NET,$mgmtService) } Catch { Switch -Wildcard ($_.Exception) { "*Ip address already exist*" {Write-Host "...Ip address already exist" -ForegroundColor Blue} Default { Write-Host $_.Exception -ForegroundColor Red} } } } # SSH Service if ($SSHenaled -eq "True"){ #Enable SSH and disable SSH Warning Write-Host "Configuring SSH Service on $ESXiHost started..." -ForegroundColor Green $SSHService = $ESXiHost | Get-VMHostService | where {$_.Key -eq 'TSM-SSH'} Start-VMHostService -HostService $SSHService -Confirm:$false | Out-Null Set-VMHostService -HostService $SSHService -Policy Automatic | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name UserVars.SuppressShellWarning | Set-AdvancedSetting -Value 1 -Confirm:$false | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name UserVars.ESXiShellInteractiveTimeOut | Set-AdvancedSetting -Value $SSHTimeout -Confirm:$false | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name UserVars.ESXiShellTimeOut | Set-AdvancedSetting -Value $SSHTimeout -Confirm:$false | Out-Null } else{ #Disabling SSH and Enabling SSH Warning Write-Host "Configuring SSH Service on $ESXiHost started..." -ForegroundColor Green $SSHService = $ESXiHost | Get-VMHostService | where {$_.Key -eq 'TSM-SSH'} Stop-VMHostService -HostService $SSHService -Confirm:$false | Out-Null Set-VMHostService -HostService $SSHService -Policy Off | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name UserVars.SuppressShellWarning | Set-AdvancedSetting -Value 0 -Confirm:$false | Out-Null } # Syslog Servcice if ($Syslogenaled -eq "True"){ #Enabling Syslog and Configuring Write-Host "Configuring Syslog Service on $ESXiHost started..." -ForegroundColor Green $ESXiHost | Get-VMHostFirewallException |?{$_.Name -eq 'syslog'} | Set-VMHostFirewallException -Enabled:$true | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name Syslog.global.logHost | Set-AdvancedSetting -Value $SyslogServer -Confirm:$false | Out-Null } else{ #Disabling Syslog Write-Host "Disabling Syslog Service on $ESXiHost started..." -ForegroundColor Green $ESXiHost | Get-VMHostFirewallException |?{$_.Name -eq 'syslog'} | Set-VMHostFirewallException -Enabled:$false | Out-Null Get-AdvancedSetting -Entity $ESXiHost.name -Name Syslog.global.logHost | Set-AdvancedSetting -Value "" -Confirm:$false | Out-Null } } Disconnect-VIServer -Force -Confirm:$false