Public/Export-NSPFortiGateCsv.ps1
|
function Export-NSPFortiGateCsv { <# .SYNOPSIS Writes one CSV per FortiOS section, plus a policy access report. .DESCRIPTION Parses all captures together and writes <Prefix>_<section>.csv for each requested section present in them. When firewall policies are present it also writes <Prefix>_policy-access.csv (see Get-NSPFortiGatePolicyAccess). Returns the files written. With -UsedByPolicy, object sections (addresses, services, users and groups, RADIUS/LDAP servers, IPsec tunnels, zones) keep only entries the policies reference, directly or through nested groups. Other sections are written whole. .PARAMETER Path Capture files, parsed together. Wildcards are accepted. .PARAMETER OutputDirectory Defaults to the folder of the first capture. .PARAMETER Prefix File name prefix. Defaults to the capture's name for one file, else 'FortiGate'. .PARAMETER Section Section paths to write; wildcards allowed. Defaults to every section with a named column layout. '*' writes every section found. .PARAMETER Delimiter Joins multiple values in one cell. Use "`n" for line breaks in Excel. .PARAMETER NoDefaults Leave settings that 'show' omitted blank instead of filling the FortiOS default. .EXAMPLE Export-NSPFortiGateCsv -Path .\captures\*.txt -OutputDirectory .\out -Prefix FGT01 -UsedByPolicy .EXAMPLE Export-NSPFortiGateCsv -Path .\full-config.conf -Section * -OutputDirectory .\dump #> [CmdletBinding()] [OutputType([System.IO.FileInfo])] param( [Parameter(Mandatory, Position = 0)][ValidateNotNullOrEmpty()][string[]]$Path, [string]$OutputDirectory, [string]$Prefix, [string[]]$Section, [ValidateNotNull()][string]$Delimiter = '; ', [switch]$UsedByPolicy, [switch]$IncludeSecrets, [switch]$NoDefaults ) $tree = Read-NSPFortiGateInput -Path $Path $first = @(foreach ($item in $Path) { if (Test-Path -LiteralPath $item) { Get-Item -LiteralPath $item } else { Get-Item -Path $item } }) if (-not $OutputDirectory) { $OutputDirectory = $first[0].DirectoryName } if (-not $Prefix) { $Prefix = if ($first.Count -eq 1) { $first[0].BaseName } else { 'FortiGate' } } if (-not $Section) { $Section = @((Get-NSPFortiGateSchema).Keys) } if (-not (Test-Path -LiteralPath $OutputDirectory)) { New-Item -ItemType Directory -Path $OutputDirectory -Force | Out-Null } $encoding = if ($PSVersionTable.PSVersion.Major -ge 6) { 'utf8BOM' } else { 'UTF8' } $analysis = Get-NSPFortiGatePolicyAnalysis -Tree $tree -Delimiter $Delimiter if ($UsedByPolicy -and $analysis.PolicyCount -eq 0) { throw '-UsedByPolicy needs the firewall policy capture among the inputs.' } $kinds = Get-NSPFortiGateReferenceKind $filtered = @($kinds.Address.Sections + $kinds.Service.Sections + $kinds.User.Sections + $kinds.Interface.Sections + 'vpn ipsec phase2-interface') $groups = [ordered]@{} foreach ($found in (Find-NSPFortiGateSection -Section $tree -Pattern $Section)) { if (-not $groups.Contains($found.Path)) { $groups[$found.Path] = New-Object System.Collections.Generic.List[object] } $groups[$found.Path].Add($found) } if ($groups.Count -eq 0 -and $analysis.PolicyCount -eq 0) { Write-Warning 'None of the requested sections were found in the input.' } $write = { param([object[]]$Rows, [string]$Name) $file = Join-Path $OutputDirectory ('{0}_{1}.csv' -f $Prefix, ($Name -replace '[^\w.+-]+', '-')) $Rows | Export-Csv -LiteralPath $file -NoTypeInformation -Encoding $encoding Get-Item -LiteralPath $file } foreach ($sectionPath in $groups.Keys) { $include = if ($UsedByPolicy -and $filtered -contains $sectionPath) { $analysis.Used } else { $null } $rows = @(ConvertTo-NSPFortiGateRow -Section $groups[$sectionPath].ToArray() -Delimiter $Delimiter -IncludeSecrets:$IncludeSecrets -NoDefaults:$NoDefaults -Include $include) if ($rows.Count -eq 0) { Write-Verbose "No rows for '$sectionPath'; no file written."; continue } & $write $rows $sectionPath } if ($analysis.PolicyCount) { & $write $analysis.Rows 'policy-access' } } |