Public/Object/Address/Get-PanAddress.ps1
function Get-PanAddress { <# .SYNOPSIS Get address objects .DESCRIPTION .NOTES The -Filter parameter emulates the PAN-OS filter/search bar which is case-insensitive and searches across address object name, value, description, and tag. PAN-OS object names are case-sensitive. Case-insensitive search is provided as a nicety. For additional filtering capabilities, pipe output to Where-Object. .INPUTS PanDevice[] You can pipe a PanDevice to this cmdlet .OUTPUTS PanAddress .EXAMPLE PS> Get-PanDevice "192.168.250.250" | Get-PanAddress .EXAMPLE PS> Get-PanDevice -All | Get-PanAddress -Filter "192.168" #> [CmdletBinding(DefaultParameterSetName='NoFilter')] param( [parameter( Mandatory=$true, ValueFromPipeline=$true, HelpMessage='PanDevice against which address object(s) will be retrieved.')] [PanDevice[]] $Device, [parameter( Position=0, ParameterSetName='Filter', HelpMessage='Name or value filter for address object(s) to be retrieved. Filter applied remotely (via API) identical to filter bar behavior.')] [String] $Filter ) Begin { # Propagate -Debug and -Verbose to this module function, https://tinyurl.com/y5dcbb34 if($PSBoundParameters.Debug) { $DebugPreference = 'Continue' } if($PSBoundParameters.Verbose) { $VerbosePreference = 'Continue' } # Announce Write-Debug ($MyInvocation.MyCommand.Name + ':') # No local filtering defined. Return everything. if($PSCmdlet.ParameterSetName -eq 'NoFilter') { Write-Debug ($MyInvocation.MyCommand.Name + ': No Filter Applied') $XPathFromPanorama = "/config/panorama/vsys/entry[@name='{0}']/address/entry" $XPathFromShared = "/config/shared/address/entry" $XPathFromLocal = "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='{0}']/address/entry" } elseif($PSCmdlet.ParameterSetName -eq 'Filter') { Write-Debug ($MyInvocation.MyCommand.Name + ': Filter Applied "' + $PSBoundParameters['Filter'] + '"') $XPathFromPanorama = "/config/panorama/vsys/entry[@name='{0}']/address/entry[(contains(translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-netmask, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-range, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(fqdn, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-wildcard, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(description, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(tag, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' ))]" $XPathFromShared= "/config/shared/address/entry[(contains(translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(ip-netmask, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(ip-range, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(fqdn, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(ip-wildcard, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(description, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' )) or (contains(translate(tag, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{0}' ))]" $XPathFromLocal = "/config/devices/entry[@name='localhost.localdomain']/vsys/entry[@name='{0}']/address/entry[(contains(translate(@name, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-netmask, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-range, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(fqdn, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(ip-wildcard, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(description, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' )) or (contains(translate(tag, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz'),'{1}' ))]" } # Define here, track aggregate device aggregate results in Process block. $PanAddressAgg = [System.Collections.Generic.List[PanAddress]]@() } # Begin Block Process { foreach($DeviceCur in $PSBoundParameters['Device']) { Write-Debug ($MyInvocation.MyCommand.Name + ': Device: ' + $DeviceCur.Name) # Ensure Vsys map is up to date for current device Update-PanDeviceVsys -Device $DeviceCur # Determine necessary location xpath(s). Includes objects from Panorama (per vsys), shared, and local (per vsys) # Stored as key-value where key is the location and value is the xpath. Using [ordered] to preserve enumeration order later # Note to achieve case-insensitivity on the -Filter parameter (given PAN-OS case-sensitive) # 1) The xpaths are heavily modified (see above) with some wild contains() and translate() # 2) The -Filter contents is submitted via API as lower-case using ToLower() $XPathsToRun = [ordered]@{} # Add Panorama-sourced object xpath(s) per vsys. Panorama can push objects to each vsys. foreach($VsysCur in $DeviceCur.Vsys) { if($PSCmdlet.ParameterSetName -eq 'NoFilter') { $XPathsToRun.Add( "panorama/$VsysCur", $XPathFromPanorama -f $VsysCur) } elseif($PSCmdlet.ParameterSetName -eq 'Filter') { $XPathsToRun.Add( "panorama/$VsysCur", ($XPathFromPanorama -f $VsysCur,$PSBoundParameters['Filter'].ToLower())) } } # Add local Shared xpath if($PSCmdlet.ParameterSetName -eq 'NoFilter') { $XPathsToRun.Add( "local/shared", $XPathFromShared) } elseif($PSCmdlet.ParameterSetName -eq 'Filter') { $XPathsToRun.Add( "local/shared", ($XPathFromShared -f $PSBoundParameters['Filter'].ToLower())) } # Add local xpath(s) per vsys. foreach($VsysCur in $DeviceCur.Vsys) { if($PSCmdlet.ParameterSetName -eq 'NoFilter') { $XPathsToRun.Add( "local/$VsysCur", $XPathFromLocal -f $VsysCur) } elseif($PSCmdlet.ParameterSetName -eq 'Filter') { $XPathsToRun.Add( "local/$VsysCur", ($XPathFromLocal -f $VsysCur,$PSBoundParameters['Filter'].ToLower())) } } # Call API for determined xpath(s) foreach($XPathCur in $XPathsToRun.GetEnumerator()) { Write-Debug ($MyInvocation.MyCommand.Name + ': Device: ' + $DeviceCur.Name + ' ' + $XPathCur.Name + ' ' + $XPathCur.Value) $PanResponse = Invoke-PanXApi -Device $DeviceCur -Config -Get -XPath $XPathCur.Value if($PanResponse.Status -eq 'success') { foreach($EntryCur in $PanResponse.Result.entry) { # Determine type and value # Use .InnerText for value to accommodate cases where element has attributes like 'dirtyId' if part of candidate config if($EntryCur.'ip-netmask') { $Type = [PanAddressType]::IpNetmask if($EntryCur.'ip-netmask'.HasChildNodes) { $Value = $EntryCur.'ip-netmask'.InnerText } else { $Value = $EntryCur.'ip-netmask' } } elseif($EntryCur.'ip-range') { $Type = [PanAddressType]::IpRange if($EntryCur.'ip-range'.HasChildNodes) { $Value = $EntryCur.'ip-range'.InnerText } else { $Value = $EntryCur.'ip-range' } } elseif($EntryCur.'ip-wildcard') { $Type = [PanAddressType]::IpWildcardMask if($EntryCur.'ip-wildcard'.HasChildNodes) { $Value = $EntryCur.'ip-wildcard'.InnerText } else { $Value = $EntryCur.'ip-wildcard' } } elseif($EntryCur.fqdn) { $Type = [PanAddressType]::Fqdn if($EntryCur.fqdn.HasChildNodes) { $Value = $EntryCur.fqdn.InnerText } else { $Value = $EntryCur.fqdn } } # Determine description # Use .InnerText for value to accommodate cases where element has attributes like 'dirtyId' if part of candidate config if($EntryCur.description.HasChildNodes) { $Description = $EntryCur.description.InnerText } else { $Description = $EntryCur.description } # Determine tag member(s) # Use .InnerText for value to accommodate cases where element has attributes like 'dirtyId' if part of candidate config $Member = @() foreach($MemberCur in $EntryCur.tag.member) { if($MemberCur.HasChildNodes) { $Member += $MemberCur.InnerText } else { $Member += $MemberCur } } # Create new PanAddress object, output to pipeline (fast update for users), save to variable New-PanAddress -Name $EntryCur.name -Value $Value -Type $Type -Description $Description -Tag $Member -Device $DeviceCur -Location $XPathCur.Name | Tee-Object -Variable 'AddressFoo' # Add the new PanAddress object to aggregate. Will be counted in End block. Available for future feature as well $PanAddressAgg.Add($AddressFoo) } # foreach entry } } # foreach xpath } # foreach Device } # Process block End { Write-Debug ($MyInvocation.MyCommand.Name + ': Final address count: ' + $PanAddressAgg.Count) } # End block } # Function |