Automation

 View Only
  • 1.  Convert string back to system object when importing from CSV

    Posted Dec 07, 2015 02:22 PM

    Apologies all, another newbie question,

    I am trying to import a list of firewall rules in order to harden the ESXi hosts. I have copied out the rules in the format below, modified them in excel and saved to a csv file.

    I created a function to copy them from a source esxi host and copy them to a destination host. I would now like to do this differently and copy in from a CSV (as we can use this as documentation for each rule) in the same format. The issue I am getting is for the "AllowedIPAddresses" column, this was originally a system.object in the output from powercli but obviously a string when I import it back in.

    Ruleset AllowedIPAddresses Enabled
    activeDirectoryAll {AA.BB.28.1,AA.BB.28.2,AA.BB.124.1,AA.BB.124.2} TRUE
    CIMHttpServer {AA.BB.134.77} TRUE
    CIMHttpsServer {AA.BB.134.77} TRUE
    CIMSLP {AA.BB.21.128/26} TRUE
    cmmds {All} FALSE
    dhcp {All} FALSE
    DHCPv6 {All} FALSE
    dns {AA.BB.28.1,AA.BB.28.2,AA.BB.124.1,AA.BB.124.2} TRUE
    DVFilter {All} FALSE
    DVSSync {AA.BB.136.0/24} TRUE
    faultTolerance {AA.BB.136.0/24} TRUE
    fdm {AA.BB.136.0/24} TRUE
    ftpClient {All} FALSE
    gdbserver {All} FALSE
    HBR {All} FALSE
    httpClient {AA.BB.134.78} TRUE
    IKED {All} FALSE
    ipfam {All} FALSE
    iSCSI {All} FALSE
    N1KV-Distributed-NetFlow {All} TRUE
    N1KV-L3-Ctrl {AA.BB.141.1,AA.BB.136.0/24} TRUE
    N1KV-L3-VNService {AA.BB.141.1} TRUE
    NFC {AA.BB.134.77,AA.BB.136.0/24} TRUE
    nfsClient {All} FALSE
    ntpClient {AA.BB.31.123,AA.BB.127.123} TRUE
    rabbitmqproxy {All} FALSE
    rdt {All} FALSE
    remoteSerialPort {All} FALSE
    snmp {All} FALSE
    sshClient {All} FALSE
    sshServer {AA.BB.134.77,AA.BB.98.41,AA.BB.2.41,AA.BB.21.128/26} TRUE
    syslog {AA.71.AA.10} TRUE
    updateManager {AA.BB.134.78} TRUE
    vMotion {All} TRUE
    vprobeServer {All} FALSE
    vpxHeartbeats {AA.BB.134.77} TRUE
    vsanvp {AA.BB.134.77} TRUE
    vSPC {All} FALSE
    vSphereClient {AA.BB.134.77,AA.BB.134.78,AA.BB.21.128/26} TRUE
    webAccess {All} FALSE
    WOL {All} TRUE

    My question is how to I create the "AllowedIPAddresses" as a system.object when I import the {IP1, IP2, IP3} back in and I can compare and do foreach loops again, against the destination hosts settings.

    The function is below. I am sure there is a better way of doing what I am doing but I understand this way :smileywink:

    # $SrcVIHost = 'Host1'

    $DstVIHost = 'Host2'

    $vCenterServer = '127.0.0.1'

    $applychanges = 'yes'

    $SrcFWFile = 'Rules.csv'

    Connect-VIServer -Server $vCenterServer | Out-Null

    Function Copy-FwSettings  {

        param

        (

            [Object]

            $CurrentSetting

        )

    #    *** old code to copy settings from host ***

    #    $SrcEsxcli = Get-EsxCli -VMHost $SrcVIHost

    #    if($SrcEsxcli -ne $null){

    #        $Srcfwenabled = $SrcEsxcli.network.firewall.ruleset.list() | Where-Object { $_.Name -eq $CurrentSetting }  | Select-Object Name, Enabled

    #        $SrcfwIpList = $Srcesxcli.network.firewall.ruleset.allowedip.list($CurrentSetting) | Select-Object Ruleset, AllowedIPAddresses   

    #    }

    #   Copy settings from CSV file

        $Srcdata  | Select-Object Ruleset, IPAllowed, Enabled

        if($Srcdata -ne $null){

            $Srcfwenabled = $Srcdata  | where-object { $_.Ruleset -eq $CurrentSetting.ruleset } | Select-Object Ruleset, Enabled

            $SrcfwIpList = $Srcdata | where-object { $_.Ruleset -eq $CurrentSetting.ruleset } |Select-Object Ruleset, IPAllowedIPAddresses

        }

    #   Get destination host current settings.

        $DstEsxcli = Get-EsxCli -VMHost $DstVIHost

        if($DstEsxcli -ne $null){

            $Dstfwenabled = $DstEsxcli.network.firewall.ruleset.list() | Where-Object { $_.Name -eq $CurrentSetting }  | Select-Object Name, Enabled

            $DstfwIpList = $Dstesxcli.network.firewall.ruleset.allowedip.list($CurrentSetting) | Select-Object Ruleset, AllowedIPAddresses

        }

    #   Compare Firewall rulesets for a  difference

        $diff = Compare-Object -DifferenceObject $SrcfwIpList -ReferenceObject $DstfwIpList -Property AllowedIpAddresses

        #Checking if FW rule $CurrentSetting should be enabled for all IP Addresses...

        If (($Srcfwenabled.enabled -eq $Dstfwenabled.enabled) -and ($Srcfwenabled.enabled -eq $true) -and ($SrcfwIpList.AllowedIPAddresses -eq 'All') -and ($DestfwIpList.AllowedIPAddresses -eq 'All')) {

            write-host "The $CurrentSetting rule is already enabled for all IP Addresses"  -ForegroundColor Green

        }

        #Checking if FW rule $CurrentSetting is disabled on both systems...

        elseif (($Srcfwenabled.enabled -eq $false) -and ($Dstfwenabled.enabled -eq $false)) {

            Write-host "The rule $CurrentSetting is already disabled"

        }

        #Write-Host "Checking if FW rule $CurrentSetting should be disabled on the destination Host...

        elseif (($Srcfwenabled.enabled -eq $false) -and ($Dstfwenabled.enabled -eq $true)) {

            write-host "The $CurrentSetting needs to be disabled on the destination host"

            if ($ApplyChanges -eq 'Yes') {

                $DstEsxCli.network.firewall.ruleset.set($true, $false, $CurrentSetting) # Sets “AllowedAll” to $true, “Enabled” to $false on rule set defined by function

                $DstEsxcli.network.firewall.refresh() # Reloads the firewall rules

            }

            else {

                write-Host 'Changes Disabled not Disabling firewall Rule' -foregroundcolor 'Yellow'

            }

        }

        #Checking if FW rule $CurrentSetting should be enabled on the destination Host and allow all IP's...

        elseif (($Srcfwenabled.enabled -eq $true) -and ($Dstfwenabled.enabled -eq $false)) {

            write-host "The $CurrentSetting needs to be enabled on the destination host and allow all IP Addresses"

            if ($ApplyChanges -eq 'Yes') {

                $DstEsxCli.network.firewall.ruleset.set($true, $true, $CurrentSetting) # Sets “AllowedAll” to $true, “Enabled” to $true on rule set defined by function

                $DstEsxcli.network.firewall.refresh() # Reloads the firewall rules

            }

            else {

                write-Host 'Changes Disabled not enabling firewall Rule' -foregroundcolor 'Yellow'

            }

        }

      # Checking if FW rule $CurrentSetting should be enabled on the destination Host and allow specific IP's...

        elseif (($Srcfwenabled.enabled -eq $true) -and ($Srcfwenabled.enabled -eq $true) -and ($SrcfwIpList.AllowedIPAddresses -ne 'All')) {

            if ($DstfwIpList.AllowedIPAddresses -eq 'All') {

                write-host "The $CurrentSetting needs to be enabled on the destination host and allow specific IP Addresses"

                if ($ApplyChanges -eq 'Yes') {

                    Write-Host 'Setting firewall ruleset'

                    $DstEsxCli.network.firewall.ruleset.set($false, $true, $CurrentSetting) # Sets “AllowedAll” to $false, “Enabled” to $true on rule set defined by function

                    $DstEsxcli.network.firewall.refresh() # Reloads the firewall rules

                }

                else {

                    Write-Host "Changes disabled not changing Firewall config for $CurrentSetting"  -foregroundcolor 'Yellow'

                }

            }

            else {

                write-host "The $CurrentSetting is already enabled on the destination host and allow specific IP Addresses" -ForegroundColor 'Green'

            }

            If ($diff -eq $null) {

                Write-Host "The rule $CurrentSetting is enabled and configured correctly and the Allowed IP's are already correct" -ForegroundColor 'Green'

            }

            else {

                if ($ApplyChanges -eq 'Yes') {

                    # Removing Old IP Addresses.

                    If ($DstfwIpList.AllowedIPAddresses -ne 'All'){

                        foreach ($DIP in $DstfwIpList.AllowedIPAddresses) {

                            $DstEsxCli.network.firewall.ruleset.allowedip.remove("$DIP", "$CurrentSetting")

                            Write-Host "$CurrentSetting Allowed IP Addresses Changed. Removed $DIP"

                        }

                    }

                    # Adding IP Addresses.

                    Write-Host 'Adding the correct IP Addresses'

                    foreach ($SIP in $SrcfwIpList.AllowedIPAddresses) {

                        $DstEsxCli.network.firewall.ruleset.allowedip.add("$SIP", "$CurrentSetting")

                        Write-Host "$CurrentSetting Allowed IP Addresses Changed. Added $SIP"

                    }

                }

                else {

                    write-Host 'Changes Disabled not applying' -foregroundcolor 'Yellow'

                }

            $DstEsxcli.network.firewall.refresh() # Reloads the firewall rules

            }

        }

        else {

            Write-Host 'There was an issue with FW configuration' -ForegroundColor 'Red'

        }

    }

    $Srcdata = import-csv -path $SrcFWFile

    Foreach ($CurrentSetting in $Scrdata) {

        Copy-FwSettings $CurrentSetting.Ruleset

        }

    Many thanks for any ideas or answers to give me some clues.

    Buzz



  • 2.  RE: Convert string back to system object when importing from CSV

    Posted Dec 07, 2015 03:06 PM

    "AllowedIPAddresses" as a system.object

    Maybe the split function will help in that case (however maybe it will not create a system.object)

    Using it on the AllowedIPAddresses with "," as a separator.



  • 3.  RE: Convert string back to system object when importing from CSV

    Posted Dec 07, 2015 08:24 PM

    Thanks for the reply I really appreciate it.

    Your reply got me thinking. I don't know whether it matters if its a system.object or not, aren't they both arrays?

    I have simplified what I am trying to do, by removing the full function, to its bare minimum. I **think** I need to somehow make the AllowedIPAddresses an array rather than string. this is basically what I am struggling with

    $SrcFWFile = 'c:\temp\Rules.csv'

    $Srcdata = import-csv -path $SrcFWFile 

    # $Srcdata  | Select-Object Ruleset, AllowedIPAddresses , Enabled

        $Srcdata = import-csv -path $SrcFWFile

    foreach ($currentsetting in $Srcdata) {

        if($Srcdata -ne $null){

            $Srcfwenabled = $Srcdata  | Where-Object { $_.Ruleset -eq $CurrentSetting.Ruleset }  | Select-Object Ruleset, Enabled

            $SrcfwIpList = $Srcdata | Where-Object { $_.Ruleset -eq $CurrentSetting.Ruleset }  | Select-Object Ruleset, AllowedIPAddresses

        }

        $type = $SrcfwIpList.AllowedIPAddresses

        $SrcfwIpList.Ruleset, $type.GetType().Name, $SrcfwIpList.AllowedIPAddresses

    }



  • 4.  RE: Convert string back to system object when importing from CSV

    Posted Dec 08, 2015 11:28 AM

    I changed the code slightly to display the member types

    # Load Windows PowerShell cmdlets for managing vSphere

    Add-PsSnapin VMware.VimAutomation.Core -ea 'SilentlyContinue'

    $DstVIHost = 'Host2'

    $applychanges = 'yes'

    $SrcFWFile = 'c:\temp\Rules.csv'

    $vCenterServer = '127.0.0.1'

    $applychanges = 'yes'

    $CurrentSetting = 'sshServer'

    Connect-VIServer -Server $vCenterServer | Out-Null

        $DstEsxcli = Get-EsxCli -VMHost $DstVIHost

        if($DstEsxcli -ne $null){

            $Dstfwenabled = $DstEsxcli.network.firewall.ruleset.list() | Where-Object { $_.Name -eq $CurrentSetting }  | Select-Object Name, Enabled

            $DstfwIpList = $Dstesxcli.network.firewall.ruleset.allowedip.list($CurrentSetting) | Select-Object Ruleset, AllowedIPAddresses

        }

    $Srcdata = import-csv -path $SrcFWFile  

    # $Srcdata  | Select-Object Ruleset, AllowedIPAddresses , Enabled

        $Srcdata = @(import-csv -path $SrcFWFile)

    foreach ($currentsetting in $Srcdata) {

        if($Srcdata -ne $null){

            $Srcfwenabled = $Srcdata  | Where-Object { $_.Ruleset -eq $CurrentSetting.Ruleset }  | Select-Object Ruleset, Enabled

            $SrcfwIpList = $Srcdata | Where-Object { $_.Ruleset -eq $CurrentSetting.Ruleset }  | Select-Object Ruleset, AllowedIPAddresses

        }

    }

        $SrcfwIpList | get-Member

        $DstfwIpList | Get-Member

    This gives the output

       TypeName: Selected.System.Management.Automation.PSCustomObject

    Name                             MemberType        Definition                           

    ----                                  ----------                 ----------                           

    Equals                            Method                bool Equals(System.Object obj)       

    GetHashCode                 Method                int GetHashCode()                    

    GetType                         Method                type GetType()                       

    ToString                         Method                string ToString()                    

    AllowedIPAddresses       NoteProperty       System.String AllowedIPAddresses={All}

    Ruleset                          NoteProperty       System.String Ruleset=WOL            

       TypeName: Selected.VMware.VimAutomation.ViCore.Impl.V1.EsxCli.EsxCliObjectImpl

    Name                             MemberType       Definition                                       

    ----                                  ----------                ----------                                       

    Equals                           Method               bool Equals(System.Object obj)                   

    GetHashCode                 Method              int GetHashCode()                                

    GetType                         Method               type GetType()                                   

    ToString                         Method               string ToString()                                

    AllowedIPAddresses       NoteProperty      System.Object[] AllowedIPAddresses=System.Object[]

    Ruleset                          NoteProperty      System.String Ruleset=sshServer  

    I am now fairly sure that I was partially correct with my original statement when I suggested import the "AllowedIPAddresses" as a system.object. Unfortunately, I am only a white belt at powershell and a little lost with regards to using split or another method to manipulate the string {IP1, IP2, IP3} and make them usable within the array.

    Thanks



  • 5.  RE: Convert string back to system object when importing from CSV
    Best Answer

    Posted Dec 08, 2015 10:18 PM

    Back to the start
    Is there a specific reason to use ESXCLI command instead of the API?

    Please check the HostFirewallSystem

    In general it is better to use the API and use esxcli only if something is not available via the API.

    If you want to continue with esxcli

    $DstEsxCli.network.firewall.ruleset.set($true, $false, $CurrentSetting)

    $esxcli.network.firewall.ruleset.set($allowedall,$enabled,$rulesetid)

    .PARAMETER allowedall

    Set to true to allowed all ip, set to false to use allowed ip list.

    .PARAMETER enabled

    Set to true to enable ruleset, set to false to disable it.

    .PARAMETER rulesetid

    The label of the ruleset.

    [System.Nullable[boolean]]$allowedall,

    [System.Nullable[boolean]]$enabled,

    [string]$rulesetid,

    $DstEsxCli.network.firewall.ruleset.allowedip.remove("$DIP", "$CurrentSetting")

    $esxcli.network.firewall.ruleset.allowedip.remove($ipaddress,$rulesetid)

    .PARAMETER ipaddress

    Allowed ip address/range for the ruleset.

    .PARAMETER rulesetid

    The label of the ruleset.

    [string]$ipaddress,

    [string]$rulesetid,

    $DstEsxCli.network.firewall.ruleset.allowedip.add("$SIP", "$CurrentSetting")

    $esxcli.network.firewall.ruleset.allowedip.add($ipaddress,$rulesetid)

    .PARAMETER ipaddress

    Allowed ip address/range for the ruleset.

    .PARAMETER rulesetid

    The label of the ruleset.

    [string]$ipaddress,

    [string]$rulesetid,

    All parameters above have been extracted from get-esxli on steroids‌ and these functions have been generated from information directly obtained from get-esxcli for all namespaces.

    The key point is that none of these functions require as a parameter an object of type:

    TypeName: "Selected.VMware.VimAutomation.ViCore.Impl.V1.EsxCli.EsxCliObjectImpl"

    So you don't need to convert back to a "Selected.VMware.VimAutomation.ViCore.Impl.V1.EsxCli.EsxCliObjectImpl" consequently the title of this topic is not relevant anymore.

    And by the way this type of object will be returned for ANY get-esxcli command.

    If you need to split your initial csv table in many lines (One for each IP) you can use

    $MyTable = Import-csv "YourPath\firewall.csv" -Delimiter `t

    $NewTable = $MyTable | foreach-object{

    $MyRow = $_

    ($_.ALLowedIPAddresses -replace'[{}]','').split(",") | foreach-object{

                $Output = New-Object -Type PSObject -Prop ([ordered]@{

                  'RuleSet'= $MyRow.RuleSet

                  'ALLowedIPAddresses' = $_

                  'Enabled' = $MyRow.Enabled

                })       

                Return $Output

    }

    }

    $NewTable


    The result is:

    PowerCLI C:\> $NewTable

    RuleSet                  ALLowedIPAddresses Enabled

    -------                  ------------------ -------

    activeDirectoryAll       AA.BB.28.1         TRUE

    activeDirectoryAll       AA.BB.28.2         TRUE

    activeDirectoryAll       AA.BB.124.1        TRUE

    activeDirectoryAll       AA.BB.124.2        TRUE

    CIMHttpServer            AA.BB.134.77       TRUE

    CIMHttpsServer           AA.BB.134.77       TRUE

    CIMSLP                   AA.BB.21.128/26    TRUE

    cmmds                    All                FALSE

    ****

    Fot the import i have used tab as a delimiter. (Tab was used in the example you have provided)

    -replace'[{}]','

    is used to remove the characters{}

    .split(",")

    As discussed earlier

    If and only if "activeDirectoryAll" is the ruleset ID (I am not able to test) then you should be in position to do for example:

    $NewTable | foreach-object {

    $DstEsxCli.network.firewall.ruleset.allowedip.add($_.ALLowedIPAddresses, "$_.RuleSet")

    }

    Or if you just want an object with an array in "AllowedIPAddresses"

      $NewTable = $MyTable | foreach-object{

                $Output = New-Object -Type PSObject -Prop ([ordered]@{

                  'RuleSet'= $_.RuleSet

                  'ALLowedIPAddresses' =  ($_.ALLowedIPAddresses -replace'[{}]','').split(",")

                  'Enabled' = $_.Enabled

                })         

                Return $Output

    }

       $NewTable

    $NewTable and $MyTable will look the same...

    But

    $MyTable.allowedIPAddresses

    $NewTable.allowedIPAddresses

    Will show that you have now an array within ALLowedIPAddresses and not a long string.



  • 6.  RE: Convert string back to system object when importing from CSV

    Posted Dec 09, 2015 03:39 PM

    Thanks very much helped me out a lot