Public/FortiGate/Get-PwFgAnalysis.ps1
function Get-PwFgAnalysis { [CmdletBinding()] <# .SYNOPSIS Performs config analysis on ASA from config file or backup. #> Param ( [Parameter(Mandatory = $True, Position = 0, ParameterSetName = 'config')] [string]$ConfigPath ) #region setup ##################################################### $VerbosePrefix = "Get-PwFgAnalysis:" if (Test-Path -Path $ConfigPath -PathType Leaf) { # Check that file exists $ConfigPath = Resolve-Path $ConfigPath $ConfigArray = Get-Content $ConfigPath # Setup ExcelPath $BaseName = (Get-ChildItem -Path $ConfigPath).BaseName $ExcelPath = Join-Path -Path (Split-Path -Path $ConfigPath) -ChildPath "$BaseName`.xlsx" } else { Throw "$VerbosePrefix ConfigPath does not exist: $ConfigPath" } # check for ImportExcel module try { Import-Module ImportExcel } catch { Throw "$VerbosePrefix This cmdlet requires ImportExcel module. https://github.com/dfinke/ImportExcel" } ##################################################### #endregion setup #region interfaces ##################################################### Write-Verbose "$VerbosePrefix Getting Interfaces" $WorksheetName = 'Interfaces' $Interfaces = Get-PwFgInterface -ConfigArray $ConfigArray -Verbose:$false $Excel = $Interfaces | Select-Object Name, Comment, Vdom, Category, IpAddress, VlanId, IsDhcpClient, InterfaceType, ParentInterface, @{Name = "AggregateMember"; Expression = { $_.AggregateMember -join [Environment]::NewLine } }, @{Name = "AllowedMgmtMethods"; Expression = { $_.AllowedMgmtMethods -join [Environment]::NewLine } }, IsManagement, IsPPPoE ` | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Verbose:$false -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() $WrapColumns += 'J' $WrapColumns += 'K' foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion interfaces #region staticroutes ##################################################### Write-Verbose "$VerbosePrefix Getting Static Routes" $WorksheetName = 'StaticRoutes' $StaticRoutes = Get-PwFgStaticRoute -ConfigArray $ConfigArray -Verbose:$false $Excel = $StaticRoutes | Select-Object Vdom, Destination, Interface, Nexthop, Metric, Comment ` | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Verbose:$false -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion staticroutes #region networkobjects ##################################################### Write-Verbose "$VerbosePrefix Getting Network Objects" $WorksheetName = 'NetworkObjects' $NetworkObjects = Get-PwFgNetworkObject -ConfigArray $ConfigArray -Verbose:$false $Excel = $NetworkObjects | Select-Object Name, Comment, Vdom, @{Name = "Member"; Expression = { $_.Member -join [Environment]::NewLine } } ` | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Verbose:$false -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() $WrapColumns += 'D' foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion networkobjects #region serviceobjects ##################################################### Write-Verbose "$VerbosePrefix Getting Service Objects" $WorksheetName = 'ServiceObjects' $ServiceObjects = Get-PwFgServiceObject -ConfigArray $ConfigArray -Verbose:$false $Excel = $ServiceObjects | Select-Object Name, Comment, Vdom, Category, Protocol, @{Name = "DestinationPort"; Expression = { $_.DestinationPort -join [Environment]::NewLine } }, @{Name = "Member"; Expression = { $_.Member -join [Environment]::NewLine } } ` | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Verbose:$false -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() $WrapColumns += 'F' $WrapColumns += 'G' foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion serviceobjects #region securitypolicies ##################################################### Write-Verbose "$VerbosePrefix Getting Security Policies" $WorksheetName = 'SecurityPolicy' $SecurityPolicies = Get-PwFgSecurityPolicy -ConfigArray $ConfigArray -Verbose:$false $Excel = $SecurityPolicies | Select-Object Number, Action, Vdom, Enabled, @{Name = "SourceInterface"; Expression = { $_.SourceInterface -join [Environment]::NewLine } }, @{Name = "DestinationInterface"; Expression = { $_.DestinationInterface -join [Environment]::NewLine } }, @{Name = "Source"; Expression = { $_.Source -join [Environment]::NewLine } }, @{Name = "SourceUser"; Expression = { $_.SourceUser -join [Environment]::NewLine } }, @{Name = "Destination"; Expression = { $_.Destination -join [Environment]::NewLine } }, @{Name = "Service"; Expression = { $_.Service -join [Environment]::NewLine } }, @{Name = "Application"; Expression = { $_.Application -join [Environment]::NewLine } }, Comment | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Verbose:$false -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() $WrapColumns += 'E' $WrapColumns += 'F' $WrapColumns += 'G' $WrapColumns += 'H' $WrapColumns += 'I' $WrapColumns += 'J' $WrapColumns += 'K' foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion securitypolicies #region resolvedsecuritypolicies ##################################################### Write-Verbose "$VerbosePrefix Resolving Security Policies" $WorksheetName = 'ResolvedSecurityPolicy' $ResolvedSecurityPolicies = $SecurityPolicies | Resolve-PwSecurityPolicy -NetworkObjects $NetworkObjects -ServiceObjects $ServiceObjects -FirewallType 'Fortigate' -Verbose:$false $global:rpol = $ResolvedSecurityPolicies $global:expath = $ExcelPath $Excel = $ResolvedSecurityPolicies | Select-Object Number, Action, Vdom, Enabled, @{Name = "SourceInterface"; Expression = { $_.SourceInterface -join [Environment]::NewLine } }, @{Name = "DestinationInterface"; Expression = { $_.DestinationInterface -join [Environment]::NewLine } }, @{Name = "Source"; Expression = { $_.Source -join [Environment]::NewLine } }, @{Name = "ResolvedSource"; Expression = { $_.ResolvedSource -join [Environment]::NewLine } }, @{Name = "SourceUser"; Expression = { $_.SourceUser -join [Environment]::NewLine } }, @{Name = "Service"; Expression = { $_.Service -join [Environment]::NewLine } }, @{Name = "ResolvedService"; Expression = { $_.ResolvedService -join [Environment]::NewLine } }, @{Name = "DestinationPort"; Expression = { $_.DestinationPort -join [Environment]::NewLine } }, @{Name = "ResolvedDestinationPort"; Expression = { $_.ResolvedDestinationPort -join [Environment]::NewLine } }, @{Name = "Application"; Expression = { $_.Application -join [Environment]::NewLine } }, Comment | Export-Excel -Path $ExcelPath -WorksheetName $WorksheetName -Calculate -FreezeTopRow -AutoSize -PassThru # add word wrap $WrapColumns = @() $WrapColumns += 'E' $WrapColumns += 'F' $WrapColumns += 'G' $WrapColumns += 'H' $WrapColumns += 'I' $WrapColumns += 'J' $WrapColumns += 'K' $WrapColumns += 'L' $WrapColumns += 'M' $WrapColumns += 'N' foreach ($col in $WrapColumns) { $Range = $Excel.Workbook.Worksheets[$WorksheetName].Dimension.Address -replace 'A1', "$col`2" -replace ':[A-Z]+', ":$col" Set-Format -WorkSheet $Excel.Workbook.Worksheets[$WorksheetName] -Range $Range -WrapText } Close-ExcelPackage $Excel ##################################################### #endregion resolvedsecuritypolicies <# Write-Verbose "Getting Objects" $Objects = Get-PwAsaObject -ConfigPath $ConfigPath -Verbose:$false $NetworkObjects = $Objects | Where-Object { $_.GetType().Name -eq 'NetworkObject' } $ServiceObjects = $Objects | Where-Object { $_.GetType().Name -eq 'ServiceObject' } Write-Verbose "Resolving Access Policies" $ResolvedAccessPolicies = $AccessPolicies | Resolve-PwSecurityPolicy -NetworkObjects $NetworkObjects -ServiceObjects $ServiceObjects -FirewallType 'asa' -Verbose:$false Write-Verbose "Getting Nat Policies" $NatPolicies = Get-PwAsaNatPolicy -ConfigPath $ConfigPath -Verbose:$false Write-Verbose "Resolving Nat Policies" $ResolvedNatPolicies = $NatPolicies | Resolve-PwNatPolicy -NetworkObjects $NetworkObjects -ServiceObjects $ServiceObjects -FirewallType 'asa' -Verbose:$false # remove natexempts $InterestingNats = $ResolvedNatPolicies | Where-Object { !($_.NatExempt) } $global:InterestingNats = $InterestingNats # look for 32 bit only Nats $IpRx = [regex] '^(\d+)\.(\d+)\.(\d+)\.(\d+)$' $InterestingNats = $InterestingNats | Where-Object { ($_.ResolvedOriginalSource -match '/32') -or ($_.ResolvedOriginalSource -eq '') -or ($IpRx.Match($_.ResolvedOriginalSource).Success) } $InterestingNats = $InterestingNats | Where-Object { ($_.ResolvedOriginalDestination -match '/32') -or ($_.ResolvedOriginalDestination -eq '') -or ($IpRx.Match($_.ResolvedOriginalDestination).Success) } $InterestingNats = $InterestingNats | Where-Object { ($_.ResolvedTranslatedSource -match '/32') -or ($_.ResolvedTranslatedSource -eq '') -or ($IpRx.Match($_.ResolvedTranslatedSource).Success) } $InterestingNats = $InterestingNats | Where-Object { ($_.ResolvedTranslatedDestination -match '/32') -or ($_.ResolvedTranslatedDestination -eq '') -or ($IpRx.Match($_.ResolvedTranslatedDestination).Success) } # filter for public IPs $PublicNatsOnly = @() foreach ($nat in $InterestingNats) { $PublicNat = $false if ($nat.ResolvedOriginalSource -ne "") { if (!(Test-IpInRange -ContainingNetwork 192.168.0.0/16 -ContainedNetwork $nat.ResolvedOriginalSource) -and !(Test-IpInRange -ContainingNetwork 172.16.0.0/12 -ContainedNetwork $nat.ResolvedOriginalSource) -and !(Test-IpInRange -ContainingNetwork 10.0.0.0/8 -ContainedNetwork $nat.ResolvedOriginalSource)) { $PublicNat = $true } } if ($nat.ResolvedOriginalDestination -ne "") { if (!(Test-IpInRange -ContainingNetwork 192.168.0.0/16 -ContainedNetwork $nat.ResolvedOriginalDestination) -and !(Test-IpInRange -ContainingNetwork 172.16.0.0/12 -ContainedNetwork $nat.ResolvedOriginalDestination) -and !(Test-IpInRange -ContainingNetwork 10.0.0.0/8 -ContainedNetwork $nat.ResolvedOriginalDestination)) { $PublicNat = $true } } if ($nat.ResolvedTranslatedSource -ne "") { if (!(Test-IpInRange -ContainingNetwork 192.168.0.0/16 -ContainedNetwork $nat.ResolvedTranslatedSource) -and !(Test-IpInRange -ContainingNetwork 172.16.0.0/12 -ContainedNetwork $nat.ResolvedTranslatedSource) -and !(Test-IpInRange -ContainingNetwork 10.0.0.0/8 -ContainedNetwork $nat.ResolvedTranslatedSource)) { $PublicNat = $true } } if ($nat.ResolvedTranslatedDestination -ne "") { if (!(Test-IpInRange -ContainingNetwork 192.168.0.0/16 -ContainedNetwork $nat.ResolvedTranslatedDestination) -and !(Test-IpInRange -ContainingNetwork 172.16.0.0/12 -ContainedNetwork $nat.ResolvedTranslatedDestination) -and !(Test-IpInRange -ContainingNetwork 10.0.0.0/8 -ContainedNetwork $nat.ResolvedTranslatedDestination)) { $PublicNat = $true } } if ($PublicNat) { $PublicNatsOnly += $nat } } # Generate Nat Report $NatSummary = @() foreach ($nat in $PublicNatsOnly) { if (!(Test-IpInRange -ContainingNetwork 192.168.0.0/16 -ContainedNetwork $nat.ResolvedOriginalSource) -and !(Test-IpInRange -ContainingNetwork 172.16.0.0/12 -ContainedNetwork $nat.ResolvedOriginalSource) -and !(Test-IpInRange -ContainingNetwork 10.0.0.0/8 -ContainedNetwork $nat.ResolvedOriginalSource)) { $NatInternalAddress = $nat.ResolvedTranslatedSource -replace '/32', '' $NatExternalAddress = $nat.ResolvedOriginalSource -replace '/32', '' } else { $NatInternalAddress = $nat.ResolvedOriginalSource -replace '/32', '' $NatExternalAddress = $nat.ResolvedTranslatedSource -replace '/32', '' } # Nat Name $ObjectLookup = $NetworkObjects | Where-Object { $_.Member -contains "$NatInternalAddress/32" } if ($nat.Name) { $NatObjectName = $nat.Name } elseif ($nat.OriginalSource -match '[a-z][A-Z]') { $NatObjectName = $nat.OriginalSource } elseif ($nat.TranslatedSource -match '[a-z][A-Z]') { $NatObjectName = $nat.TranslatedSource } elseif ($ObjectLookup) { $NatObjectName = $ObjectLookup.Name } else { $NatObjectName = $NatInternalAddress } $AccessLookup = $ResolvedAccessPolicies | Where-Object { ($_.ResolvedDestination -eq "$NatInternalAddress/32") -or ($_.ResolvedDestination -eq "$NatExternalAddress/32") } | Select-Object Source, ResolvedSource, Service, ResolvedService -Unique $Sources = ($AccessLookup.Source | Select-Object -Unique) foreach ($source in $Sources) { $NatSourceName = $source $ResolvedSource = $AccessLookup | Where-Object { $_.Source -eq $source } | Select-Object ResolvedSource -Unique foreach ($rs in $ResolvedSource) { $UniqueServices = $AccessLookup | Where-Object { $_.Source -eq $NatSourceName } | Select-Object Service -Unique $NatServiceName = $UniqueServices foreach ($uservice in $NatServiceName) { #$NatServiceName = $uservice.Service $ResolvedService = $AccessLookup | Where-Object { ($_.Source -eq $NatSourceName) -and ($_.Service -eq $uservice.Service) } | Select-Object ResolvedService -Unique foreach ($rservice in $ResolvedService) { $new = "" | Select-Object ObjectName, InternalAddress, ExternalAddress, SourceName, SourceAddress, ServiceName, Service $NatSummary += $new $new.ObjectName = $NatObjectName $new.InternalAddress = $NatInternalAddress $new.ExternalAddress = $NatExternalAddress $new.SourceName = $NatSourceName $new.SourceAddress = $rs.ResolvedSource $new.ServiceName = $uservice.Service[0] $new.Service = $rservice.ResolvedService } } } } } $Interfaces = Get-PwAsaInterface -ConfigPath $ConfigPath $SourceInterfaceMap = @{ } $DestinationInterfaceMap = @{ } foreach ($interface in $Interfaces) { if ($interface.AccessList) { $AclName = $interface.AccessList if ($interface.AccessListDirection -eq 'in') { $SourceInterfaceMap.$AclName = $interface.NameIf } elseif ($interface.AccessListDirection -eq 'out') { $DestinationInterfaceMap.$AclName = $interface.NameIf } } } #$BaseName = (Get-ChildItem -Path $ConfigPath).BaseName #$ExcelPath = Join-Path -Path (Split-Path -Path $ConfigPath) -ChildPath "$BaseName`.xlsx" $NatSummary | Export-Excel -Path $ExcelPath -WorksheetName 'Overview' -Verbose:$false $ResolvedNatPolicies | Select-Object Number, Comment, Enabled, SourceInterface, DestinationInterface, ` OriginalSource, ResolvedOriginalSource, OriginalDestination, ResolvedOriginalDestination, OriginalService, ResolvedOriginalService, TranslatedSource, ResolvedTranslatedSource, TranslatedDestination, ResolvedTranslatedDestination, TranslatedService, ResolvedTranslatedService, SourceTranslationType, DestinationTranslationType, ProxyArp, RouteLookup, NatExempt | Export-Excel -Path $ExcelPath -WorksheetName 'NAT' -Verbose:$false $ResolvedAccessPolicies | Select-Object AccessList, AclType, Number, Action, ` #SourceInterface, DestinationInterface, @{ Name = 'SourceInterface'; Expression = { $SourceInterfaceMap."$($_.AccessList)" } }, @{ Name = 'DestinationInterface'; Expression = { $DestinationInterfaceMap."$($_.AccessList)" } }, @{ Name = 'Source'; Expression = { $_.Source -join ',' } }, ResolvedSource, @{ Name = 'Destination'; Expression = { $_.Destination -join ',' } }, ResolvedDestination, Protocol, SourcePort, ResolvedSourcePort, DestinationPort, ResolvedDestinationPort, @{ Name = 'Service'; Expression = { $_.Service -join ',' } }, ResolvedService, Comment, Enabled, NewRule, Status, Notes | Export-Excel -Path $ExcelPath -WorksheetName 'AccessPolicies' -FreezeTopRow -Verbose:$false ##################################################### #endregion asa #> #$global:Excel = $Excel #Close-ExcelPackage $Excel } |