Home > Powershell, VMWare > Create ESXi Host firewall rules using PowerCli

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

}
Categories: Powershell, VMWare Tags:
  1. No comments yet.
  1. No trackbacks yet.
You must be logged in to post a comment.