Create ESXi Host firewall rules using PowerCli
Recently, I needed to create some custom firewall rules on ESX hosts (lots of them) – for some Syslog servers that were in addition to our existing Syslog servers.
Here was my appraoach (note – Firewall rules will be lost at reboot unless you hack bootbank, or make the changes using custom VIBs)
http://kb.vmware.com/selfservice/microsites/search.do?language=en_US&cmd=displayKC&externalId=2007381
http://cormachogan.com/2014/03/28/adding-bespoke-firewall-rules-to-esxi/
The code has dependecnies on Posh-SSH (freely available, excellent automation tool)
# PowerCLI Script for enabling SSH, setting firewall and disable SSH alert in vCenter # multiple dependencies # https://github.com/darkoperator/Posh-SSH # PowerCli #Requires -Modules ActiveDirectory #Requires -Version 4 #Requires -Modules Posh-SSH # Sample update import-module posh-ssh add-pssnapin vm* $vmhostname = read-host "Please provide target ESX hostname" Connect-VIServer <viservname> $Credential = Get-Credential -Message "Please provide root user password for $vmhostname" -UserName "root" # enable SSH on ESX host (function below) Set-SshOnVmHost -VMHostName $vmhostname -Status On # Create firewall rule on ESX host new-FireWallRuleonVmHost -VMHostName $vmhostname -direction outbound -protocol tcp -porttype dst -serviceID myServicename -port 1234 -enabled false -required false # Display the change $esxcli = Get-EsxCli -VMHost $vmhostname $esxcli.network.firewall.ruleset.list() # Disable SSH on the host Set-SshOnVmHost -VMHostName $vmhostname -Status Off function Set-SshOnVmHost { Param( [String] $VMHostName, [ValidateSet('On','Off')] [String] $Status ) write-host "Configuring SSH on host: $($vmHost.Name) to $Status" -fore Yellow if((Get-VMHostService -VMHost $vmhostname | where {$_.Key -eq "TSM-SSH"}).Policy -ne "$Status"){ Write-Host "Setting SSH service policy to automatic $status $($vmHost.Name)" Get-VMHostService -VMHost $vmhostname | where { $_.key -eq "TSM-SSH" } | Set-VMHostService -Policy "$Status" -Confirm:$false -ea 1 | Out-null } $vmhost = get-vmhost $vmhostname $esxcli = Get-EsxCli -VMHost $vmhost if($Status -eq 'On'){ if((Get-VMHostService -VMHost $vmhost | where {$_.Key -eq "TSM-SSH"}).Running -ne $true){ Write-Host "Starting SSH service on $($vmHost.Name)" Start-VMHostService -confirm:$false -HostService (Get-VMHost $vmHost | Get-VMHostService | Where { $_.Key -eq "TSM-SSH"}) | Out-null $ip = (Get-WmiObject -class win32_NetworkAdapterConfiguration -Filter 'ipenabled = "true"').ipaddress[0] if($esxcli -ne $null){ if($ip.count -ne 1){ $ip = read-host "Please provide the IP address that should be to access this host via SSH" } try{ test-ipaddress $ip if(($esxcli.network.firewall.ruleset.allowedip.list("sshServer") | select AllowedIPAddresses).AllowedIPAddresses -eq "All"){ Write-Host "Changing the sshServer firewall configuration" $esxcli.network.firewall.ruleset.set($false, $true, "sshServer") if(($esxcli.network.firewall.ruleset.allowedip.list("sshServer") | select AllowedIPAddresses).AllowedIPAddresses -notmatch "$ip"){ $esxcli.network.firewall.ruleset.allowedip.add("$ip", "sshServer") } $esxcli.network.firewall.refresh() } } catch { throw "Unable to configure IP restirctions on Firewall when enabling SSH $_" } } } } else{ if((Get-VMHostService -VMHost $vmhost | where {$_.Key -eq "TSM-SSH"}).Running -ne $false){ Write-Host "Stopping SSH service on $($vmHost.Name)" Stop-VMHostService -confirm:$false -HostService (Get-VMHost $vmHost | Get-VMHostService | Where { $_.Key -eq "TSM-SSH"}) | Out-null write-host "Set Firewall rule too allow all IPs for SSH, but disable the service" if(($esxcli.network.firewall.ruleset.allowedip.list("sshServer") | select AllowedIPAddresses).AllowedIPAddresses -ne "All"){ Write-Host "Changing the sshServer firewall configuration" $esxcli.network.firewall.ruleset.set($true, $true, "sshServer") $esxcli.network.firewall.refresh() } } } # End Comment if(($vmHost | Get-AdvancedSetting | Where {$_.Name -eq "UserVars.SuppressShellWarning"}).Value -ne "1"){ Write-Host "Suppress the SSH warning message" $vmHost | Get-AdvancedSetting | Where {$_.Name -eq "UserVars.SuppressShellWarning"} | Set-AdvancedSetting -Value "1" -Confirm:$false | Out-null } } function Test-IPaddress { [CmdletBinding()] Param ( [Parameter(Mandatory=$true, ValueFromPipelineByPropertyName=$true, Position=0)] [ValidateScript({$_ -match [IPAddress]$_ })] [string] $IPAddress ) [ipaddress]$IPAddress } # function for creation of a new Firewall rulle on an ESX host function new-FireWallRuleonVmHost { Param( [Parameter(Mandatory=$true)] [String] $VMHostName, [Parameter(Mandatory=$true)] [ValidateSet('inbound','outbound')] [String] $direction, [Parameter(Mandatory=$true)] [ValidateSet('tcp','udp')] [String] $protocol, [Parameter(Mandatory=$true)] [ValidateSet('dst','src')] [String] $porttype, [Parameter(Mandatory=$true)] [String]$serviceID, [ValidateRange(0,65536)] [int]$port, [Parameter(Mandatory=$true)] [ValidateSet('true','false')] [String] $enabled, [Parameter(Mandatory=$true)] [ValidateSet('true','false')] [String] $required ) # Create an SSH Session to the target $ssh = New-SSHSession -ComputerName $VMHostName -Credential $credential # Get the SSH Session's ID $sessionId = $($ssh.Index) # Copy original service.xml to .bak Invoke-SSHCommand -Command "cp /etc/vmware/firewall/service.xml /etc/vmware/firewall/service.xml.bak" -Index $sessionId # Allow write access over existing service.xml Invoke-SSHCommand -Command "chmod 644 /etc/vmware/firewall/service.xml" -Index $sessionId # Change the sticky bit Invoke-SSHCommand -Command "chmod +t /etc/vmware/firewall/service.xml" -Index $sessionId # Create a local copy of the service.xml file $out = %{Invoke-SSHCommand -Command "cat /etc/vmware/firewall/service.xml" -Index $sessionId} $out.Output > c:\temp\services.xml 1$xml = $out.Output # Sort through IDs to find the highest current value (assuming $ids = @(); $list = $xml.ConfigRoot.service | %{$_.id} | ?{$_ -match '0'} | %{$ids += [int]$_} [string]$id = "`'00" + (($ids | sort-object -Descending | select-object -First 1) + 1).ToString() + "`'"; # insert xml for new service custom xml before closing the closing <`/ConfigRoot`> $newXml = (get-content C:\temp\servicestmp.xml | Select-String -Pattern "`<`/ConfigRoot`>" -NotMatch) + @" <service id=$id> <id>$serviceID</id> <rule> <direction>$direction</direction> <protocol>$protocol</protocol> <porttype>$porttype</porttype> <port>$port</port> </rule> <enabled>$enabled</enabled> <required>$required</required> </service> </ConfigRoot> "@ > "C:\temp\services.xml" # copy new xml to services.xml on vm host Set-SCPFile -ComputerName $VMHostName -Credential $credential -LocalFile C:\temp\services.xml -RemoteFile /etc/vmware/firewall/service.xml # Prevet write access over service.xml Invoke-SSHCommand -Command "chmod 444 /etc/vmware/firewall/service.xml" -Index $sessionId # Change the sticky bit Invoke-SSHCommand -Command "chmod -t /etc/vmware/firewall/service.xml" -Index $sessionId # Refresh Firewall Rules on ESX host Invoke-SSHCommand -Command "esxcli network firewall refresh" -Index $sessionId # remove the SSH Session that you created remove-sshSession -index $sessionId }