|
|
@@ -0,0 +1,1139 @@
|
|
|
+#Requires -Version 5.1
|
|
|
+<#
|
|
|
+.SYNOPSIS
|
|
|
+ NetScaler NITRO API Configuration Extractor
|
|
|
+ Connects live to a NetScaler ADC via the NITRO REST API and extracts
|
|
|
+ configuration objects similar to the file-based extractor.
|
|
|
+
|
|
|
+.DESCRIPTION
|
|
|
+ Prompts for NSIP, Username, and Password, authenticates via NITRO,
|
|
|
+ then lets you select a vServer and extracts all dependent objects
|
|
|
+ (services, monitors, policies, SSL certs, auth actions, etc.).
|
|
|
+
|
|
|
+.PARAMETER nsip
|
|
|
+ IP or FQDN of the NetScaler management interface. Prompted if not supplied.
|
|
|
+
|
|
|
+.PARAMETER username
|
|
|
+ NetScaler admin username. Prompted if not supplied.
|
|
|
+
|
|
|
+.PARAMETER password
|
|
|
+ NetScaler admin password as SecureString. Prompted if not supplied.
|
|
|
+
|
|
|
+.PARAMETER vserver
|
|
|
+ Partial or full vServer name to filter. Leave blank to list all.
|
|
|
+
|
|
|
+.PARAMETER outputFile
|
|
|
+ Path to save extracted config. "screen" to print only. Prompted if blank.
|
|
|
+
|
|
|
+.PARAMETER textEditor
|
|
|
+ Text editor to open output file after extraction.
|
|
|
+
|
|
|
+.PARAMETER useSSL
|
|
|
+ Use HTTPS (default). Set to $false to use HTTP (not recommended).
|
|
|
+
|
|
|
+.PARAMETER skipCertCheck
|
|
|
+ Skip SSL certificate validation (useful for self-signed certs on lab appliances).
|
|
|
+
|
|
|
+.PARAMETER nFactorNestingLevel
|
|
|
+ How many nFactor Next Factor levels to traverse (default 5).
|
|
|
+
|
|
|
+.NOTES
|
|
|
+ Change Log
|
|
|
+ ----------
|
|
|
+ 2025 Mar - Initial release based on NITRO API v2 (NetScaler 12.x / 13.x / 14.x)
|
|
|
+ Supports: lb, cs, vpn, authentication, gslb vServers
|
|
|
+ Supports: services, serviceGroups, monitors, servers
|
|
|
+ Supports: SSL certs/profiles/ciphers/policies
|
|
|
+ Supports: rewrite, responder, appfw, cmp, cache, transform policies
|
|
|
+ Supports: AAA / nFactor (ldap, radius, saml, cert, tacacs, oauth, etc.)
|
|
|
+ Supports: GSLB sites/services
|
|
|
+ Supports: System settings (features, modes, HA, IPs, routes, DNS)
|
|
|
+#>
|
|
|
+
|
|
|
+param (
|
|
|
+ [string] $nsip = "",
|
|
|
+ [string] $username = "",
|
|
|
+ [securestring] $password = $null,
|
|
|
+ [string] $vserver = "",
|
|
|
+ [string] $outputFile = "$env:USERPROFILE\Downloads\nsnitro_config.conf",
|
|
|
+ [string] $textEditor = "notepad++.exe",
|
|
|
+ [bool] $useSSL = $true,
|
|
|
+ [switch] $skipCertCheck,
|
|
|
+ [switch] $cswBind,
|
|
|
+ [int] $nFactorNestingLevel = 5
|
|
|
+)
|
|
|
+
|
|
|
+Set-StrictMode -Off
|
|
|
+$ErrorActionPreference = "Stop"
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# TLS / Cert helpers
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+if ($skipCertCheck) {
|
|
|
+ if ($PSVersionTable.PSVersion.Major -ge 6) {
|
|
|
+ # PowerShell Core / 7+
|
|
|
+ $script:InvokeParams = @{ SkipCertificateCheck = $true }
|
|
|
+ } else {
|
|
|
+ # Windows PowerShell 5.x – add a permissive policy once
|
|
|
+ if (-not ([System.Management.Automation.PSTypeName]'TrustAllCertsPolicy').Type) {
|
|
|
+ Add-Type @"
|
|
|
+using System.Net;
|
|
|
+using System.Security.Cryptography.X509Certificates;
|
|
|
+public class TrustAllCertsPolicy : ICertificatePolicy {
|
|
|
+ public bool CheckValidationResult(
|
|
|
+ ServicePoint srvPoint, X509Certificate certificate,
|
|
|
+ WebRequest request, int certificateProblem) { return true; }
|
|
|
+}
|
|
|
+"@
|
|
|
+ }
|
|
|
+ [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy
|
|
|
+ $script:InvokeParams = @{}
|
|
|
+ }
|
|
|
+} else {
|
|
|
+ $script:InvokeParams = @{}
|
|
|
+}
|
|
|
+
|
|
|
+[System.Net.ServicePointManager]::SecurityProtocol =
|
|
|
+ [System.Net.SecurityProtocolType]::Tls12 -bor
|
|
|
+ [System.Net.SecurityProtocolType]::Tls13
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Prompt helpers
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+function Prompt-Input ([string]$Prompt, [string]$Default = "") {
|
|
|
+ $val = Read-Host $Prompt
|
|
|
+ if (-not $val -and $Default) { return $Default }
|
|
|
+ return $val
|
|
|
+}
|
|
|
+
|
|
|
+function Get-OutputFilePath {
|
|
|
+ if ($IsMacOS) {
|
|
|
+ $f = (('tell application "SystemUIServer"' + "`n" + 'activate' + "`n" +
|
|
|
+ 'set theName to POSIX path of (choose file name default name "nsnitro_config.conf" with prompt "Save extracted config as")' + "`n" +
|
|
|
+ 'end tell' | osascript -s s) -split '"')[1]
|
|
|
+ return $f
|
|
|
+ }
|
|
|
+ [System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms") | Out-Null
|
|
|
+ $d = New-Object System.Windows.Forms.SaveFileDialog
|
|
|
+ $d.Title = "Save Extracted NetScaler Config"
|
|
|
+ $d.Filter = "NetScaler Config (*.conf)|*.conf|All files (*.*)|*.*"
|
|
|
+ $d.ShowDialog() | Out-Null
|
|
|
+ return $d.FileName
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Credential / connection setup
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+cls
|
|
|
+Write-Host "╔══════════════════════════════════════════════════════════╗" -ForegroundColor Cyan
|
|
|
+Write-Host "║ NetScaler NITRO API Configuration Extractor ║" -ForegroundColor Cyan
|
|
|
+Write-Host "╚══════════════════════════════════════════════════════════╝" -ForegroundColor Cyan
|
|
|
+Write-Host ""
|
|
|
+
|
|
|
+if (-not $nsip) { $nsip = Prompt-Input "Enter NetScaler Management IP or FQDN" }
|
|
|
+if (-not $username) { $username = Prompt-Input "Enter Username" "nsroot" }
|
|
|
+if (-not $password) { $password = Read-Host "Enter Password" -AsSecureString }
|
|
|
+
|
|
|
+$proto = if ($useSSL) { "https" } else { "http" }
|
|
|
+$baseUrl = $proto + "://" + $nsip + "/nitro/v1"
|
|
|
+
|
|
|
+$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password)
|
|
|
+$plainPwd = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)
|
|
|
+[System.Runtime.InteropServices.Marshal]::ZeroFreeBSTR($BSTR)
|
|
|
+
|
|
|
+# Session cookie store
|
|
|
+$script:Session = $null
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# NITRO Helper Functions
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+
|
|
|
+function Invoke-Nitro {
|
|
|
+ param(
|
|
|
+ [string] $Method = "GET",
|
|
|
+ [string] $Resource,
|
|
|
+ [string] $Action = "",
|
|
|
+ [object] $Body = $null,
|
|
|
+ [hashtable] $Query = @{}
|
|
|
+ )
|
|
|
+
|
|
|
+ $uri = "$baseUrl/config/$Resource"
|
|
|
+ if ($Query.Count -gt 0) {
|
|
|
+ $qs = ($Query.GetEnumerator() | ForEach-Object { "$($_.Key)=$([uri]::EscapeDataString($_.Value))" }) -join "&"
|
|
|
+ $uri += "?$qs"
|
|
|
+ }
|
|
|
+ if ($Action) { $uri += "?action=$Action" }
|
|
|
+
|
|
|
+ $headers = @{ "Content-Type" = "application/json" }
|
|
|
+ if ($script:AuthToken) { $headers["Cookie"] = "NITRO_AUTH_TOKEN=$($script:AuthToken)" }
|
|
|
+
|
|
|
+ $splat = @{
|
|
|
+ Uri = $uri
|
|
|
+ Method = $Method
|
|
|
+ Headers = $headers
|
|
|
+ WebSession = $script:Session
|
|
|
+ UseBasicParsing = $true
|
|
|
+ } + $script:InvokeParams
|
|
|
+
|
|
|
+ if ($Body) { $splat["Body"] = ($Body | ConvertTo-Json -Depth 10 -Compress) }
|
|
|
+
|
|
|
+ try {
|
|
|
+ $resp = Invoke-WebRequest @splat
|
|
|
+ $json = $resp.Content | ConvertFrom-Json
|
|
|
+ return $json
|
|
|
+ } catch {
|
|
|
+ $msg = $_.Exception.Message
|
|
|
+ if ($_.Exception.Response) {
|
|
|
+ try {
|
|
|
+ $stream = $_.Exception.Response.GetResponseStream()
|
|
|
+ $reader = New-Object System.IO.StreamReader($stream)
|
|
|
+ $errBody = $reader.ReadToEnd() | ConvertFrom-Json
|
|
|
+ $msg = "NITRO Error $($errBody.errorcode): $($errBody.message)"
|
|
|
+ } catch {}
|
|
|
+ }
|
|
|
+ Write-Warning "NITRO call failed [$Method $Resource]: $msg"
|
|
|
+ return $null
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Get-NitroObjects {
|
|
|
+ param(
|
|
|
+ [string] $Resource,
|
|
|
+ [string] $Filter = "",
|
|
|
+ [string[]] $Attrs = @(),
|
|
|
+ [int] $PageSize = 0
|
|
|
+ )
|
|
|
+
|
|
|
+ $query = @{}
|
|
|
+ if ($Filter) { $query["filter"] = $Filter }
|
|
|
+ if ($Attrs) { $query["attrs"] = ($Attrs -join ",") }
|
|
|
+ if ($PageSize -gt 0) { $query["count"] = "yes" }
|
|
|
+
|
|
|
+ $result = Invoke-Nitro -Method GET -Resource $Resource -Query $query
|
|
|
+ if (-not $result) { return @() }
|
|
|
+
|
|
|
+ # The resource name is the key in the response object
|
|
|
+ $key = $Resource -replace "/.*","" # strip any sub-resource path
|
|
|
+ if ($result.PSObject.Properties[$key]) {
|
|
|
+ return @($result.$key)
|
|
|
+ }
|
|
|
+ return @()
|
|
|
+}
|
|
|
+
|
|
|
+function Get-NitroBinding {
|
|
|
+ param([string]$Resource, [string]$Name, [string]$BindType)
|
|
|
+ $enc = [uri]::EscapeDataString($Name)
|
|
|
+ $path = "${Resource}/${enc}"
|
|
|
+ if ($BindType) { $path += "?type=$BindType" }
|
|
|
+ $result = Invoke-Nitro -Method GET -Resource $path
|
|
|
+ if (-not $result) { return @() }
|
|
|
+ $key = ($Resource -replace "/.*","") + "_binding"
|
|
|
+ if ($result.PSObject.Properties[$key]) { return @($result.$key) }
|
|
|
+ # some bindings return the type directly
|
|
|
+ $key2 = ($Resource -replace "/.*","") + "_" + $BindType + "_binding"
|
|
|
+ if ($result.PSObject.Properties[$key2]) { return @($result.$key2) }
|
|
|
+ return @()
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Login
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+Write-Host "`nConnecting to $baseUrl ..." -ForegroundColor Yellow
|
|
|
+
|
|
|
+$loginBody = @{
|
|
|
+ login = @{
|
|
|
+ username = $username
|
|
|
+ password = $plainPwd
|
|
|
+ timeout = 3600
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Use SessionVariable to capture cookies
|
|
|
+$loginUri = "$baseUrl/config/login"
|
|
|
+$loginHeaders = @{ "Content-Type" = "application/json" }
|
|
|
+$loginSplat = @{
|
|
|
+ Uri = $loginUri
|
|
|
+ Method = "POST"
|
|
|
+ Headers = $loginHeaders
|
|
|
+ Body = ($loginBody | ConvertTo-Json -Compress)
|
|
|
+ SessionVariable = "webSession"
|
|
|
+ UseBasicParsing = $true
|
|
|
+} + $script:InvokeParams
|
|
|
+
|
|
|
+try {
|
|
|
+ $loginResp = Invoke-WebRequest @loginSplat
|
|
|
+ $script:Session = $webSession
|
|
|
+ $loginJson = $loginResp.Content | ConvertFrom-Json
|
|
|
+ # Some versions return a token, others just use the session cookie
|
|
|
+ if ($loginJson.PSObject.Properties["login"]) {
|
|
|
+ $script:AuthToken = $loginJson.login.sessionid
|
|
|
+ }
|
|
|
+ Write-Host "✔ Login successful." -ForegroundColor Green
|
|
|
+} catch {
|
|
|
+ Write-Host "✘ Login failed: $($_.Exception.Message)" -ForegroundColor Red
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+$plainPwd = $null # clear plain-text password from memory
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Output helpers
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+$script:outputLines = [System.Collections.Generic.List[string]]::new()
|
|
|
+
|
|
|
+function Out-Line ([string]$line) {
|
|
|
+ $script:outputLines.Add($line)
|
|
|
+}
|
|
|
+
|
|
|
+function Out-Section ([string]$title) {
|
|
|
+ Out-Line ""
|
|
|
+ Out-Line "# $title"
|
|
|
+ Out-Line "# $("-" * $title.Length)"
|
|
|
+}
|
|
|
+
|
|
|
+function Write-Output-File {
|
|
|
+ param([string]$path)
|
|
|
+ $content = $script:outputLines -join "`n"
|
|
|
+ # UNIX line endings
|
|
|
+ [IO.File]::WriteAllText($path, $content)
|
|
|
+ Write-Host "`nConfig written to: $path" -ForegroundColor Green
|
|
|
+}
|
|
|
+
|
|
|
+function Format-NitroObject {
|
|
|
+ # Convert a NITRO object (PSCustomObject) into a NetScaler CLI-like line
|
|
|
+ param([string]$Cmd, [object]$Obj)
|
|
|
+ $line = $Cmd
|
|
|
+ foreach ($prop in $Obj.PSObject.Properties) {
|
|
|
+ $val = $prop.Value
|
|
|
+ if ($null -eq $val -or $val -eq "" -or $val -eq 0 -or $val -eq $false) { continue }
|
|
|
+ if ($val -is [array] -and $val.Count -eq 0) { continue }
|
|
|
+ $name = $prop.Name
|
|
|
+ # skip internal / metadata fields
|
|
|
+ if ($name -in @("__count","bindpoint","stateflag","flags","statechangetimesec",
|
|
|
+ "statechangetimelarge","statechangetime","tickssincelaststatechange",
|
|
|
+ "cursynfloodrate","vsvrbindsvcip","vsvrbindsvcport","policysubtype",
|
|
|
+ "curstate","status","monstatcode","monstatparam1","monstatparam2",
|
|
|
+ "monstatparam3","responsetime","riseapbrstatsmsgcode","lbvserver",
|
|
|
+ "nodefaultbindings","translationip","translationmask","weight",
|
|
|
+ "dynamicweight","dbslb","totalrequestbytes","totalresponsebytes",
|
|
|
+ "curclntconnections","cursrvrconnections","surgecount","svrestablishedconn",
|
|
|
+ "requestsinflight","avgsvrtttfb","curpersistencesessions")) { continue }
|
|
|
+
|
|
|
+ if ($val -is [array]) {
|
|
|
+ $val = $val -join ","
|
|
|
+ }
|
|
|
+ # quote values with spaces
|
|
|
+ if ("$val" -match "\s") { $val = "`"$val`"" }
|
|
|
+ $line += " -$name $val"
|
|
|
+ }
|
|
|
+ return $line
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Fetch & catalogue all main object types up front (cached hashtable)
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+Write-Host "`nFetching configuration objects from NetScaler..." -ForegroundColor Yellow
|
|
|
+
|
|
|
+$cache = @{}
|
|
|
+
|
|
|
+function Fetch-Cache ([string]$Type) {
|
|
|
+ if (-not $cache.ContainsKey($Type)) {
|
|
|
+ $objs = Get-NitroObjects -Resource $Type
|
|
|
+ $cache[$Type] = $objs
|
|
|
+ Write-Host (" Loaded {0,-40} ({1} objects)" -f $Type, $objs.Count)
|
|
|
+ }
|
|
|
+ return $cache[$Type]
|
|
|
+}
|
|
|
+
|
|
|
+# Pre-load common types
|
|
|
+$types = @(
|
|
|
+ "lbvserver","csvserver","vpnvserver","authenticationvserver","gslbvserver",
|
|
|
+ "service","servicegroup","server","lbmonitor",
|
|
|
+ "sslvserver","sslcertkey","sslprofile","sslcipher","sslpolicy","sslaction",
|
|
|
+ "rewritepolicy","rewriteaction","rewritepolicylabel",
|
|
|
+ "responderpolicy","responderaction","responderpolicylabel",
|
|
|
+ "cspolicy","csaction","cspolicylabel",
|
|
|
+ "appfwpolicy","appfwprofile","appfwpolicylabel",
|
|
|
+ "cmppolicy","cmpaction","cmppolicylabel",
|
|
|
+ "cachepolicy","cachecontentgroup","cacheselector","cachepolicylabel",
|
|
|
+ "transformpolicy","transformaction","transformprofile","transformpolicylabel",
|
|
|
+ "authenticationldapaction","authenticationldappolicy",
|
|
|
+ "authenticationradiusaction","authenticationradiuspolicy",
|
|
|
+ "authenticationsamlaction","authenticationsamlpolicy",
|
|
|
+ "authenticationcertaction","authenticationcertpolicy",
|
|
|
+ "authenticationtacacsaction","authenticationtacacspolicy",
|
|
|
+ "authenticationpolicy","authenticationpolicylabel","authenticationloginschemapolicy",
|
|
|
+ "authenticationloginschema","authenticationauthnprofile",
|
|
|
+ "vpnsessionpolicy","vpnsessionaction","vpntrafficpolicy","vpntrafficaction",
|
|
|
+ "tmsessionpolicy","tmsessionaction","tmtrafficpolicy","tmtrafficaction",
|
|
|
+ "vpnclientlessaccesspolicy","vpnclientlessaccessprofile",
|
|
|
+ "authorizationpolicy","authorizationpolicylabel",
|
|
|
+ "auditsyslogpolicy","auditsyslogaction","auditnslogpolicy","auditnslogaction",
|
|
|
+ "netprofile","nshttpprofile","nstcpprofile","dnssuffix","dnsprofile","dnsview",
|
|
|
+ "gslbsite","gslbservice","nslimitidentifier","nslimitselector",
|
|
|
+ "nsacl","route","nsip","vlan","interface","haparam","hanode","nsfeature","nsmode",
|
|
|
+ "systemparameter","systemuser","systemgroup"
|
|
|
+)
|
|
|
+
|
|
|
+foreach ($t in $types) {
|
|
|
+ $null = Fetch-Cache $t
|
|
|
+}
|
|
|
+
|
|
|
+Write-Host "`n✔ Object fetch complete." -ForegroundColor Green
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# vServer selection
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+Write-Host ""
|
|
|
+
|
|
|
+# Collect all vServers from all types
|
|
|
+$allVServers = @()
|
|
|
+foreach ($vsType in @("lbvserver","csvserver","vpnvserver","authenticationvserver","gslbvserver")) {
|
|
|
+ foreach ($vs in $cache[$vsType]) {
|
|
|
+ $allVServers += [PSCustomObject]@{
|
|
|
+ Type = $vsType
|
|
|
+ Name = $vs.name
|
|
|
+ VIP = if ($vs.PSObject.Properties["ipv46"]) { $vs.ipv46 }
|
|
|
+ elseif ($vs.PSObject.Properties["ip"]) { $vs.ip }
|
|
|
+ else { "" }
|
|
|
+ Port = if ($vs.PSObject.Properties["port"]) { $vs.port } else { "" }
|
|
|
+ Protocol = if ($vs.PSObject.Properties["servicetype"]) { $vs.servicetype } else { "" }
|
|
|
+ State = if ($vs.PSObject.Properties["curstate"]) { $vs.curstate } else { "" }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# Filter by $vserver if provided
|
|
|
+if ($vserver) {
|
|
|
+ $filtered = $allVServers | Where-Object { $_.Name -match [regex]::Escape($vserver) }
|
|
|
+} else {
|
|
|
+ $filtered = $allVServers
|
|
|
+}
|
|
|
+
|
|
|
+if ($filtered.Count -eq 0) {
|
|
|
+ Write-Host "No vServers found matching '$vserver'." -ForegroundColor Red
|
|
|
+ exit 1
|
|
|
+}
|
|
|
+
|
|
|
+# Add System Settings option
|
|
|
+$sysOption = [PSCustomObject]@{
|
|
|
+ Type = "sys"; Name = "** System Settings **"; VIP = ""; Port = ""; Protocol = ""; State = ""
|
|
|
+}
|
|
|
+$selectionList = @($sysOption) + ($filtered | Sort-Object Type, Name)
|
|
|
+
|
|
|
+Write-Host "Select Virtual Server(s) to extract:`n"
|
|
|
+
|
|
|
+if ($IsMacOS) {
|
|
|
+ $names = $selectionList | ForEach-Object { $_.Name.Trim('"') }
|
|
|
+ $vsRaw = (('tell application "SystemUIServer"' + "`n" + 'activate' + "`n" +
|
|
|
+ 'set vserver to (choose from list {"' + ($names -join '","') + '"} with prompt "Cmd+Select Multiple vServers" with multiple selections allowed)' + "`n" +
|
|
|
+ 'end tell' | osascript -s s) -replace ', ',',')
|
|
|
+ $selectedNames = [regex]::Matches($vsRaw,'(?:([\w\s\.\*\-]+))') | ForEach-Object { $_.Value }
|
|
|
+ $selectedVServers = $selectionList | Where-Object { $selectedNames -contains $_.Name.Trim('"') }
|
|
|
+} else {
|
|
|
+ $selectedVServers = $selectionList | Out-GridView -Title "Ctrl+Select Multiple Virtual Servers to extract" -PassThru
|
|
|
+}
|
|
|
+
|
|
|
+if (-not $selectedVServers) {
|
|
|
+ Write-Host "No selection made. Exiting." -ForegroundColor Yellow; exit 0
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Output file prompt
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+if (-not $outputFile) { $outputFile = Get-OutputFilePath }
|
|
|
+if (-not $outputFile) { $outputFile = "screen" }
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Extraction Engine
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+
|
|
|
+# Lookup helpers – find object in cache by name
|
|
|
+function Get-ObjectByName ([string]$Type, [string]$Name) {
|
|
|
+ return $cache[$Type] | Where-Object { $_.name -eq $Name }
|
|
|
+}
|
|
|
+
|
|
|
+function Get-BindingsFor ([string]$BindResource, [string]$Name) {
|
|
|
+ # e.g. BindResource = "lbvserver_service_binding" Name = "vs1"
|
|
|
+ $enc = [uri]::EscapeDataString($Name)
|
|
|
+ $result = Invoke-Nitro -Method GET -Resource "${BindResource}/${enc}"
|
|
|
+ if (-not $result) { return @() }
|
|
|
+ if ($result.PSObject.Properties[$BindResource]) {
|
|
|
+ return @($result.$BindResource)
|
|
|
+ }
|
|
|
+ return @()
|
|
|
+}
|
|
|
+
|
|
|
+# ── Write object config lines ─────────────────────────────────────────────────
|
|
|
+function Write-ObjectSection ([string]$Header, [string]$Type, [string[]]$Names, [string]$ExplainText="") {
|
|
|
+ if (-not $Names -or $Names.Count -eq 0) { return }
|
|
|
+ $uniqueNames = $Names | Select-Object -Unique
|
|
|
+ Out-Section $Header
|
|
|
+ foreach ($name in $uniqueNames) {
|
|
|
+ $obj = Get-ObjectByName $Type $name
|
|
|
+ if ($obj) {
|
|
|
+ Out-Line (Format-NitroObject "add $($Type -replace 'vserver','vServer')" $obj)
|
|
|
+ } else {
|
|
|
+ Out-Line "# [not found in cache] $Type $name"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($ExplainText) { Out-Line "# *** $ExplainText" }
|
|
|
+ Out-Line ""
|
|
|
+}
|
|
|
+
|
|
|
+# ── SSL bindings helper ───────────────────────────────────────────────────────
|
|
|
+function Get-SSLObjectsForVS ([string]$VSName, [string]$VSType) {
|
|
|
+ # sslvserver bindings
|
|
|
+ $sslBindRes = "${VSType}_sslcertkey_binding"
|
|
|
+ $bindings = Get-BindingsFor $sslBindRes $VSName
|
|
|
+ $certs = @()
|
|
|
+ foreach ($b in $bindings) {
|
|
|
+ if ($b.PSObject.Properties["certkeyname"]) { $certs += $b.certkeyname }
|
|
|
+ }
|
|
|
+
|
|
|
+ # ssl profile
|
|
|
+ $sslCfg = (Invoke-Nitro -Method GET -Resource "sslvserver/$([uri]::EscapeDataString($VSName))")
|
|
|
+ $profile = ""
|
|
|
+ if ($sslCfg -and $sslCfg.PSObject.Properties["sslvserver"]) {
|
|
|
+ $profile = $sslCfg.sslvserver | Select-Object -First 1 -ExpandProperty sslprofile -ErrorAction SilentlyContinue
|
|
|
+ }
|
|
|
+
|
|
|
+ return @{ Certs = $certs; Profile = $profile }
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Per-vServer extraction
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+
|
|
|
+$extracted = @{
|
|
|
+ lbvservers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ csvservers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ vpnvservers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ authvservers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ gslbvservers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ services = [System.Collections.Generic.List[string]]::new()
|
|
|
+ servicegroups = [System.Collections.Generic.List[string]]::new()
|
|
|
+ servers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ monitors = [System.Collections.Generic.List[string]]::new()
|
|
|
+ sslcerts = [System.Collections.Generic.List[string]]::new()
|
|
|
+ sslprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ sslciphers = [System.Collections.Generic.List[string]]::new()
|
|
|
+ sslpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ sslactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ rewritepolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ rewriteactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ rewritepolicylabels = [System.Collections.Generic.List[string]]::new()
|
|
|
+ responderpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ responderactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ responderpolicylabels = [System.Collections.Generic.List[string]]::new()
|
|
|
+ cspolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ csactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ cspolicylabels = [System.Collections.Generic.List[string]]::new()
|
|
|
+ appfwpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ appfwprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ cmppolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ cachepolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ transformpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ transformactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ transformprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ ldapactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ ldappolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ radiusactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ radiuspolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ samlactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ samlidppolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ certactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ certpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ tacacsactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ tacacspolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ authpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ authpolicylabels = [System.Collections.Generic.List[string]]::new()
|
|
|
+ loginschemas = [System.Collections.Generic.List[string]]::new()
|
|
|
+ loginschemapolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ authnprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ vpnsessionpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ vpnsessionactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ vpntrafficpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ vpntrafficactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ auditsyslogpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ auditsyslogactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ auditnslogpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ auditnslogactions = [System.Collections.Generic.List[string]]::new()
|
|
|
+ authorizationpolicies = [System.Collections.Generic.List[string]]::new()
|
|
|
+ netprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ tcpprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ httpprofiles = [System.Collections.Generic.List[string]]::new()
|
|
|
+ gslbsites = [System.Collections.Generic.List[string]]::new()
|
|
|
+ gslbservices = [System.Collections.Generic.List[string]]::new()
|
|
|
+ doSys = $false
|
|
|
+}
|
|
|
+
|
|
|
+function Add-Unique ([string]$Key, [string]$Value) {
|
|
|
+ if ($Value -and -not $extracted[$Key].Contains($Value)) {
|
|
|
+ $extracted[$Key].Add($Value)
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# ── Pull bindings for an LB vServer ──────────────────────────────────────────
|
|
|
+function Process-LBvServer ([string]$Name) {
|
|
|
+ Add-Unique "lbvservers" $Name
|
|
|
+ Write-Host " Processing LB vServer: $Name"
|
|
|
+
|
|
|
+ # Service bindings
|
|
|
+ $svcBinds = Get-BindingsFor "lbvserver_service_binding" $Name
|
|
|
+ foreach ($b in $svcBinds) {
|
|
|
+ if ($b.PSObject.Properties["servicename"]) {
|
|
|
+ $sn = $b.servicename; Add-Unique "services" $sn
|
|
|
+ Process-Service $sn
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # ServiceGroup bindings
|
|
|
+ $sgBinds = Get-BindingsFor "lbvserver_servicegroup_binding" $Name
|
|
|
+ foreach ($b in $sgBinds) {
|
|
|
+ if ($b.PSObject.Properties["servicegroupname"]) {
|
|
|
+ $sg = $b.servicegroupname; Add-Unique "servicegroups" $sg
|
|
|
+ Process-ServiceGroup $sg
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # Policies
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_rewritepolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-RewritePolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_responderpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-ResponderPolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_appfwpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-AppFWPolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_cmppolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Add-Unique "cmppolicies" $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_transformpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-TransformPolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_auditsyslogpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Add-Unique "auditsyslogpolicies" $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "lbvserver_sslpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-SSLPolicy $b.policyname } }
|
|
|
+ # SSL
|
|
|
+ $ssl = Get-SSLObjectsForVS $Name "lbvserver"
|
|
|
+ foreach ($c in $ssl.Certs) { Add-Unique "sslcerts" $c }
|
|
|
+ if ($ssl.Profile) { Add-Unique "sslprofiles" $ssl.Profile }
|
|
|
+ # Profiles
|
|
|
+ $obj = Get-ObjectByName "lbvserver" $Name
|
|
|
+ if ($obj) {
|
|
|
+ if ($obj.PSObject.Properties["netprofile"] -and $obj.netprofile) { Add-Unique "netprofiles" $obj.netprofile }
|
|
|
+ if ($obj.PSObject.Properties["tcpprofilename"] -and $obj.tcpprofilename) { Add-Unique "tcpprofiles" $obj.tcpprofilename }
|
|
|
+ if ($obj.PSObject.Properties["httpprofilename"] -and $obj.httpprofilename) { Add-Unique "httpprofiles" $obj.httpprofilename }
|
|
|
+ # auth
|
|
|
+ if ($obj.PSObject.Properties["authnvsname"] -and $obj.authnvsname) { Process-AuthVServer $obj.authnvsname }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-Service ([string]$Name) {
|
|
|
+ $obj = Get-ObjectByName "service" $Name
|
|
|
+ if (-not $obj) { return }
|
|
|
+ if ($obj.PSObject.Properties["servername"] -and $obj.servername) { Add-Unique "servers" $obj.servername }
|
|
|
+ # Monitors
|
|
|
+ $mBinds = Get-BindingsFor "service_lbmonitor_binding" $Name
|
|
|
+ foreach ($b in $mBinds) { if ($b.PSObject.Properties["monitor_name"]) { Add-Unique "monitors" $b.monitor_name } }
|
|
|
+ if ($obj.PSObject.Properties["sslprofile"] -and $obj.sslprofile) { Add-Unique "sslprofiles" $obj.sslprofile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-ServiceGroup ([string]$Name) {
|
|
|
+ $obj = Get-ObjectByName "servicegroup" $Name
|
|
|
+ if (-not $obj) { return }
|
|
|
+ # Members
|
|
|
+ $mems = Get-BindingsFor "servicegroup_servicegroupmember_binding" $Name
|
|
|
+ foreach ($m in $mems) {
|
|
|
+ if ($m.PSObject.Properties["servername"] -and $m.servername) { Add-Unique "servers" $m.servername }
|
|
|
+ }
|
|
|
+ # Monitors
|
|
|
+ $mBinds = Get-BindingsFor "servicegroup_lbmonitor_binding" $Name
|
|
|
+ foreach ($b in $mBinds) { if ($b.PSObject.Properties["monitor_name"]) { Add-Unique "monitors" $b.monitor_name } }
|
|
|
+ if ($obj.PSObject.Properties["sslprofile"] -and $obj.sslprofile) { Add-Unique "sslprofiles" $obj.sslprofile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-CSvServer ([string]$Name) {
|
|
|
+ Add-Unique "csvservers" $Name
|
|
|
+ Write-Host " Processing CS vServer: $Name"
|
|
|
+ $polBinds = Get-BindingsFor "csvserver_cspolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) {
|
|
|
+ if ($b.PSObject.Properties["policyname"] -and $b.policyname) {
|
|
|
+ Add-Unique "cspolicies" $b.policyname
|
|
|
+ # Get action -> target LB
|
|
|
+ $pol = Get-ObjectByName "cspolicy" $b.policyname
|
|
|
+ if ($pol -and $pol.PSObject.Properties["action"] -and $pol.action) {
|
|
|
+ Add-Unique "csactions" $pol.action
|
|
|
+ $act = Get-ObjectByName "csaction" $pol.action
|
|
|
+ if ($act) {
|
|
|
+ if ($act.PSObject.Properties["targetlbvserver"] -and $act.targetlbvserver) { Process-LBvServer $act.targetlbvserver }
|
|
|
+ if ($act.PSObject.Properties["targetvserver"] -and $act.targetvserver) {
|
|
|
+ # Could be vpn or auth
|
|
|
+ if ($cache["vpnvserver"] | Where-Object { $_.name -eq $act.targetvserver }) { Process-VPNvServer $act.targetvserver }
|
|
|
+ if ($cache["authenticationvserver"] | Where-Object { $_.name -eq $act.targetvserver }) { Process-AuthVServer $act.targetvserver }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if ($b.PSObject.Properties["targetlbvserver"] -and $b.targetlbvserver) { Process-LBvServer $b.targetlbvserver }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # Default LB
|
|
|
+ $obj = Get-ObjectByName "csvserver" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["lbvserver"] -and $obj.lbvserver) { Process-LBvServer $obj.lbvserver }
|
|
|
+ # Policies on the CS vServer itself
|
|
|
+ $polBinds = Get-BindingsFor "csvserver_rewritepolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-RewritePolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "csvserver_responderpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-ResponderPolicy $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "csvserver_auditsyslogpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Add-Unique "auditsyslogpolicies" $b.policyname } }
|
|
|
+ $polBinds = Get-BindingsFor "csvserver_sslpolicy_binding" $Name; foreach ($b in $polBinds) { if ($b.policyname) { Process-SSLPolicy $b.policyname } }
|
|
|
+ $ssl = Get-SSLObjectsForVS $Name "csvserver"
|
|
|
+ foreach ($c in $ssl.Certs) { Add-Unique "sslcerts" $c }
|
|
|
+ if ($ssl.Profile) { Add-Unique "sslprofiles" $ssl.Profile }
|
|
|
+ if ($obj -and $obj.PSObject.Properties["netprofile"] -and $obj.netprofile) { Add-Unique "netprofiles" $obj.netprofile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-VPNvServer ([string]$Name) {
|
|
|
+ Add-Unique "vpnvservers" $Name
|
|
|
+ Write-Host " Processing VPN/Gateway vServer: $Name"
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_vpnsessionpolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-VPNSessionPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_authenticationldappolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-LDAPPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_authenticationradiuspolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-RADIUSPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_authenticationsamlpolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Add-Unique "samlidppolicies" $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_responderpolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-ResponderPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_rewritepolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-RewritePolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "vpnvserver_authenticationpolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) {
|
|
|
+ if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-AuthPolicy $b.policy }
|
|
|
+ if ($b.PSObject.Properties["nextfactor"] -and $b.nextfactor) { Process-AuthPolicyLabel $b.nextfactor }
|
|
|
+ }
|
|
|
+ $ssl = Get-SSLObjectsForVS $Name "vpnvserver"
|
|
|
+ foreach ($c in $ssl.Certs) { Add-Unique "sslcerts" $c }
|
|
|
+ if ($ssl.Profile) { Add-Unique "sslprofiles" $ssl.Profile }
|
|
|
+ $obj = Get-ObjectByName "vpnvserver" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["authnprofile"] -and $obj.authnprofile) { Process-AuthnProfile $obj.authnprofile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-AuthVServer ([string]$Name) {
|
|
|
+ Add-Unique "authvservers" $Name
|
|
|
+ Write-Host " Processing AAA/Auth vServer: $Name"
|
|
|
+ $polBinds = Get-BindingsFor "authenticationvserver_authenticationldappolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-LDAPPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "authenticationvserver_authenticationradiuspolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-RADIUSPolicy $b.policy } }
|
|
|
+ $polBinds = Get-BindingsFor "authenticationvserver_authenticationpolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) {
|
|
|
+ if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-AuthPolicy $b.policy }
|
|
|
+ if ($b.PSObject.Properties["nextfactor"] -and $b.nextfactor) { Process-AuthPolicyLabel $b.nextfactor }
|
|
|
+ }
|
|
|
+ $polBinds = Get-BindingsFor "authenticationvserver_authenticationloginschemapolicy_binding" $Name
|
|
|
+ foreach ($b in $polBinds) { if ($b.PSObject.Properties["policy"] -and $b.policy) { Process-LoginSchemaPolicy $b.policy } }
|
|
|
+ $ssl = Get-SSLObjectsForVS $Name "authenticationvserver"
|
|
|
+ foreach ($c in $ssl.Certs) { Add-Unique "sslcerts" $c }
|
|
|
+ if ($ssl.Profile) { Add-Unique "sslprofiles" $ssl.Profile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-GSLBvServer ([string]$Name) {
|
|
|
+ Add-Unique "gslbvservers" $Name
|
|
|
+ Write-Host " Processing GSLB vServer: $Name"
|
|
|
+ $svcBinds = Get-BindingsFor "gslbvserver_gslbservice_binding" $Name
|
|
|
+ foreach ($b in $svcBinds) {
|
|
|
+ if ($b.PSObject.Properties["servicename"] -and $b.servicename) {
|
|
|
+ Add-Unique "gslbservices" $b.servicename
|
|
|
+ $svc = Get-ObjectByName "gslbservice" $b.servicename
|
|
|
+ if ($svc -and $svc.PSObject.Properties["sitename"] -and $svc.sitename) { Add-Unique "gslbsites" $svc.sitename }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ $ssl = Get-SSLObjectsForVS $Name "gslbvserver"
|
|
|
+ foreach ($c in $ssl.Certs) { Add-Unique "sslcerts" $c }
|
|
|
+ if ($ssl.Profile) { Add-Unique "sslprofiles" $ssl.Profile }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-RewritePolicy ([string]$Name) {
|
|
|
+ Add-Unique "rewritepolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "rewritepolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "rewriteactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-ResponderPolicy ([string]$Name) {
|
|
|
+ Add-Unique "responderpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "responderpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "responderactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-AppFWPolicy ([string]$Name) {
|
|
|
+ Add-Unique "appfwpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "appfwpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["profilename"] -and $obj.profilename) { Add-Unique "appfwprofiles" $obj.profilename }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-TransformPolicy ([string]$Name) {
|
|
|
+ Add-Unique "transformpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "transformpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) {
|
|
|
+ Add-Unique "transformactions" $obj.action
|
|
|
+ $act = Get-ObjectByName "transformaction" $obj.action
|
|
|
+ if ($act -and $act.PSObject.Properties["profilename"] -and $act.profilename) { Add-Unique "transformprofiles" $act.profilename }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-SSLPolicy ([string]$Name) {
|
|
|
+ Add-Unique "sslpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "sslpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "sslactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-LDAPPolicy ([string]$Name) {
|
|
|
+ Add-Unique "ldappolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "authenticationldappolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "ldapactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-RADIUSPolicy ([string]$Name) {
|
|
|
+ Add-Unique "radiuspolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "authenticationradiuspolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "radiusactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-AuthPolicy ([string]$Name) {
|
|
|
+ Add-Unique "authpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "authenticationpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) {
|
|
|
+ $action = $obj.action
|
|
|
+ # Detect action type by searching sub-caches
|
|
|
+ foreach ($atype in @("authenticationldapaction","authenticationradiusaction",
|
|
|
+ "authenticationsamlaction","authenticationcertaction",
|
|
|
+ "authenticationtacacsaction")) {
|
|
|
+ if ($cache[$atype] | Where-Object { $_.name -eq $action }) {
|
|
|
+ switch ($atype) {
|
|
|
+ "authenticationldapaction" { Add-Unique "ldapactions" $action }
|
|
|
+ "authenticationradiusaction" { Add-Unique "radiusactions" $action }
|
|
|
+ "authenticationsamlaction" { Add-Unique "samlactions" $action }
|
|
|
+ "authenticationcertaction" { Add-Unique "certactions" $action }
|
|
|
+ "authenticationtacacsaction" { Add-Unique "tacacsactions" $action }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-AuthPolicyLabel ([string]$Name) {
|
|
|
+ if ($extracted["authpolicylabels"].Contains($Name)) { return }
|
|
|
+ Add-Unique "authpolicylabels" $Name
|
|
|
+ Write-Host " Processing Auth Policy Label: $Name"
|
|
|
+ $binds = Get-BindingsFor "authenticationpolicylabel_authenticationpolicy_binding" $Name
|
|
|
+ foreach ($b in $binds) {
|
|
|
+ if ($b.PSObject.Properties["policyname"] -and $b.policyname) { Process-AuthPolicy $b.policyname }
|
|
|
+ if ($b.PSObject.Properties["nextfactor"] -and $b.nextfactor) { Process-AuthPolicyLabel $b.nextfactor }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-LoginSchemaPolicy ([string]$Name) {
|
|
|
+ Add-Unique "loginschemapolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "authenticationloginschemapolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "loginschemas" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-VPNSessionPolicy ([string]$Name) {
|
|
|
+ Add-Unique "vpnsessionpolicies" $Name
|
|
|
+ $obj = Get-ObjectByName "vpnsessionpolicy" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["action"] -and $obj.action) { Add-Unique "vpnsessionactions" $obj.action }
|
|
|
+}
|
|
|
+
|
|
|
+function Process-AuthnProfile ([string]$Name) {
|
|
|
+ Add-Unique "authnprofiles" $Name
|
|
|
+ $obj = Get-ObjectByName "authenticationauthnprofile" $Name
|
|
|
+ if ($obj -and $obj.PSObject.Properties["authnvsname"] -and $obj.authnvsname) { Process-AuthVServer $obj.authnvsname }
|
|
|
+}
|
|
|
+
|
|
|
+# ── Dispatch selected vServers ────────────────────────────────────────────────
|
|
|
+Write-Host "`nExtracting configuration for selected vServers..." -ForegroundColor Yellow
|
|
|
+
|
|
|
+foreach ($sel in $selectedVServers) {
|
|
|
+ switch ($sel.Type) {
|
|
|
+ "lbvserver" { Process-LBvServer $sel.Name }
|
|
|
+ "csvserver" { Process-CSvServer $sel.Name }
|
|
|
+ "vpnvserver" { Process-VPNvServer $sel.Name }
|
|
|
+ "authenticationvserver" { Process-AuthVServer $sel.Name }
|
|
|
+ "gslbvserver" { Process-GSLBvServer $sel.Name }
|
|
|
+ "sys" { $extracted["doSys"] = $true }
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Build Output
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+Write-Host "`nBuilding output..." -ForegroundColor Yellow
|
|
|
+
|
|
|
+$vsNames = ($selectedVServers | Where-Object { $_.Type -ne "sys" } | ForEach-Object { $_.Name }) -join ", "
|
|
|
+Out-Line "# NetScaler NITRO Config Extract"
|
|
|
+Out-Line "# NSIP : $nsip"
|
|
|
+Out-Line "# Extracted : $(Get-Date -Format 'yyyy-MM-dd HH:mm:ss')"
|
|
|
+Out-Line "# vServers : $vsNames"
|
|
|
+Out-Line ""
|
|
|
+
|
|
|
+# ── Helper to emit all objects of a type ─────────────────────────────────────
|
|
|
+function Emit-Objects ([string]$SectionTitle, [string]$CacheType, [string[]]$NameList, [string]$Cmd, [string]$Note="") {
|
|
|
+ if (-not $NameList -or $NameList.Count -eq 0) { return }
|
|
|
+ Out-Section $SectionTitle
|
|
|
+ if ($Note) { Out-Line "# *** $Note" }
|
|
|
+ foreach ($n in ($NameList | Select-Object -Unique)) {
|
|
|
+ $obj = Get-ObjectByName $CacheType $n
|
|
|
+ if ($obj) {
|
|
|
+ Out-Line (Format-NitroObject $Cmd $obj)
|
|
|
+ } else {
|
|
|
+ Out-Line "# [not found in live config] $CacheType $n"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Out-Line ""
|
|
|
+}
|
|
|
+
|
|
|
+# ── System Settings ───────────────────────────────────────────────────────────
|
|
|
+if ($extracted["doSys"]) {
|
|
|
+ Out-Section "System Settings"
|
|
|
+
|
|
|
+ $sysParam = Invoke-Nitro -Method GET -Resource "systemparameter"
|
|
|
+ if ($sysParam -and $sysParam.PSObject.Properties["systemparameter"]) {
|
|
|
+ Out-Line (Format-NitroObject "set system parameter" $sysParam.systemparameter)
|
|
|
+ }
|
|
|
+
|
|
|
+ Out-Section "Enabled Features"
|
|
|
+ $features = Invoke-Nitro -Method GET -Resource "nsfeature"
|
|
|
+ if ($features -and $features.PSObject.Properties["nsfeature"]) {
|
|
|
+ $f = $features.nsfeature
|
|
|
+ $enabled = $f.PSObject.Properties | Where-Object { $_.Value -eq "YES" -or $_.Value -eq $true } | ForEach-Object { $_.Name }
|
|
|
+ Out-Line ("enable ns feature " + ($enabled -join " "))
|
|
|
+ }
|
|
|
+
|
|
|
+ Out-Section "Enabled Modes"
|
|
|
+ $modes = Invoke-Nitro -Method GET -Resource "nsmode"
|
|
|
+ if ($modes -and $modes.PSObject.Properties["nsmode"]) {
|
|
|
+ $m = $modes.nsmode
|
|
|
+ $enabledM = $m.PSObject.Properties | Where-Object { $_.Value -eq "YES" -or $_.Value -eq $true } | ForEach-Object { $_.Name }
|
|
|
+ Out-Line ("enable ns mode " + ($enabledM -join " "))
|
|
|
+ }
|
|
|
+
|
|
|
+ Out-Section "NSIP Addresses"
|
|
|
+ foreach ($ip in $cache["nsip"]) { Out-Line (Format-NitroObject "add ns ip" $ip) }
|
|
|
+
|
|
|
+ Out-Section "VLANs"
|
|
|
+ foreach ($v in $cache["vlan"]) { Out-Line (Format-NitroObject "add vlan" $v) }
|
|
|
+
|
|
|
+ Out-Section "Routes"
|
|
|
+ foreach ($r in $cache["route"]) { Out-Line (Format-NitroObject "add route" $r) }
|
|
|
+
|
|
|
+ Out-Section "HA Nodes"
|
|
|
+ foreach ($h in $cache["hanode"]) { Out-Line (Format-NitroObject "add ha node" $h) }
|
|
|
+
|
|
|
+ Out-Section "System Users"
|
|
|
+ foreach ($u in $cache["systemuser"]) { Out-Line (Format-NitroObject "add system user" $u) }
|
|
|
+
|
|
|
+ Out-Section "System Groups"
|
|
|
+ foreach ($g in $cache["systemgroup"]) { Out-Line (Format-NitroObject "add system group" $g) }
|
|
|
+
|
|
|
+ Out-Section "ACLs"
|
|
|
+ foreach ($a in $cache["nsacl"]) { Out-Line (Format-NitroObject "add ns acl" $a) }
|
|
|
+
|
|
|
+ Out-Line ""
|
|
|
+}
|
|
|
+
|
|
|
+# ── SSL ───────────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "SSL Certificates" "sslcertkey" $extracted["sslcerts"] "add ssl certKey" "Certificate files must be present in /nsconfig/ssl"
|
|
|
+Emit-Objects "SSL Profiles" "sslprofile" $extracted["sslprofiles"] "add ssl profile"
|
|
|
+Emit-Objects "SSL Policies" "sslpolicy" $extracted["sslpolicies"] "add ssl policy"
|
|
|
+Emit-Objects "SSL Actions" "sslaction" $extracted["sslactions"] "add ssl action"
|
|
|
+
|
|
|
+# ── Networking / Profiles ─────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Net Profiles" "netprofile" $extracted["netprofiles"] "add netprofile"
|
|
|
+Emit-Objects "TCP Profiles" "nstcpprofile" $extracted["tcpprofiles"] "add ns tcpProfile"
|
|
|
+Emit-Objects "HTTP Profiles" "nshttpprofile" $extracted["httpprofiles"] "add ns httpProfile"
|
|
|
+
|
|
|
+# ── Servers, Services, Monitors ──────────────────────────────────────────────
|
|
|
+Emit-Objects "Servers" "server" $extracted["servers"] "add server"
|
|
|
+Emit-Objects "Monitors" "lbmonitor" $extracted["monitors"] "add lb monitor"
|
|
|
+Emit-Objects "Services" "service" $extracted["services"] "add service"
|
|
|
+Emit-Objects "Service Groups" "servicegroup" $extracted["servicegroups"] "add serviceGroup"
|
|
|
+
|
|
|
+# ── Rewrite / Responder ───────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Rewrite Actions" "rewriteaction" $extracted["rewriteactions"] "add rewrite action"
|
|
|
+Emit-Objects "Rewrite Policies" "rewritepolicy" $extracted["rewritepolicies"] "add rewrite policy"
|
|
|
+Emit-Objects "Responder Actions" "responderaction" $extracted["responderactions"] "add responder action"
|
|
|
+Emit-Objects "Responder Policies" "responderpolicy" $extracted["responderpolicies"] "add responder policy"
|
|
|
+
|
|
|
+# ── AppFW ─────────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "AppFW Profiles" "appfwprofile" $extracted["appfwprofiles"] "add appfw profile" "Manually export/import AppFW signatures and XML schema objects"
|
|
|
+Emit-Objects "AppFW Policies" "appfwpolicy" $extracted["appfwpolicies"] "add appfw policy"
|
|
|
+
|
|
|
+# ── Compression ───────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "CMP Policies" "cmppolicy" $extracted["cmppolicies"] "add cmp policy"
|
|
|
+
|
|
|
+# ── Transform ─────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Transform Profiles" "transformprofile" $extracted["transformprofiles"] "add transform profile"
|
|
|
+Emit-Objects "Transform Actions" "transformaction" $extracted["transformactions"] "add transform action"
|
|
|
+Emit-Objects "Transform Policies" "transformpolicy" $extracted["transformpolicies"] "add transform policy"
|
|
|
+
|
|
|
+# ── CS ────────────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "CS Actions" "csaction" $extracted["csactions"] "add cs action"
|
|
|
+Emit-Objects "CS Policies" "cspolicy" $extracted["cspolicies"] "add cs policy"
|
|
|
+
|
|
|
+# ── AAA / Authentication ──────────────────────────────────────────────────────
|
|
|
+Emit-Objects "LDAP Actions" "authenticationldapaction" $extracted["ldapactions"] "add authentication ldapAction" "LDAP CA certs are in /nsconfig/truststore"
|
|
|
+Emit-Objects "LDAP Policies" "authenticationldappolicy" $extracted["ldappolicies"] "add authentication ldapPolicy"
|
|
|
+Emit-Objects "RADIUS Actions" "authenticationradiusaction" $extracted["radiusactions"] "add authentication radiusAction"
|
|
|
+Emit-Objects "RADIUS Policies" "authenticationradiuspolicy" $extracted["radiuspolicies"] "add authentication radiusPolicy"
|
|
|
+Emit-Objects "SAML Actions" "authenticationsamlaction" $extracted["samlactions"] "add authentication samlAction"
|
|
|
+Emit-Objects "Cert Actions" "authenticationcertaction" $extracted["certactions"] "add authentication certAction"
|
|
|
+Emit-Objects "TACACS Actions" "authenticationtacacsaction" $extracted["tacacsactions"] "add authentication tacacsAction"
|
|
|
+Emit-Objects "TACACS Policies" "authenticationtacacspolicy" $extracted["tacacspolicies"] "add authentication tacacsPolicy"
|
|
|
+Emit-Objects "Adv Auth Policies" "authenticationpolicy" $extracted["authpolicies"] "add authentication Policy"
|
|
|
+Emit-Objects "Auth Policy Labels" "authenticationpolicylabel" $extracted["authpolicylabels"] "add authentication policylabel"
|
|
|
+Emit-Objects "Login Schemas" "authenticationloginschema" $extracted["loginschemas"] "add authentication loginSchema"
|
|
|
+Emit-Objects "Login Schema Policies" "authenticationloginschemapolicy" $extracted["loginschemapolicies"] "add authentication loginSchemaPolicy"
|
|
|
+Emit-Objects "Authentication Profiles" "authenticationauthnprofile" $extracted["authnprofiles"] "add authentication authnProfile"
|
|
|
+
|
|
|
+# ── VPN Session ───────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "VPN Session Actions" "vpnsessionaction" $extracted["vpnsessionactions"] "add vpn sessionAction"
|
|
|
+Emit-Objects "VPN Session Policies" "vpnsessionpolicy" $extracted["vpnsessionpolicies"] "add vpn sessionPolicy"
|
|
|
+Emit-Objects "VPN Traffic Actions" "vpntrafficaction" $extracted["vpntrafficactions"] "add vpn trafficAction"
|
|
|
+Emit-Objects "VPN Traffic Policies" "vpntrafficpolicy" $extracted["vpntrafficpolicies"] "add vpn trafficPolicy"
|
|
|
+
|
|
|
+# ── Audit Syslog ──────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Audit Syslog Actions" "auditsyslogaction" $extracted["auditsyslogactions"] "add audit syslogAction"
|
|
|
+Emit-Objects "Audit Syslog Policies" "auditsyslogpolicy" $extracted["auditsyslogpolicies"] "add audit syslogPolicy"
|
|
|
+Emit-Objects "Audit NSLog Actions" "auditnslogaction" $extracted["auditnslogactions"] "add audit nslogAction"
|
|
|
+Emit-Objects "Audit NSLog Policies" "auditnslogpolicy" $extracted["auditnslogpolicies"] "add audit nslogPolicy"
|
|
|
+
|
|
|
+# ── Authorization ─────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Authorization Policies" "authorizationpolicy" $extracted["authorizationpolicies"] "add authorization policy"
|
|
|
+
|
|
|
+# ── GSLB ─────────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "GSLB Sites" "gslbsite" $extracted["gslbsites"] "add gslb site"
|
|
|
+Emit-Objects "GSLB Services" "gslbservice" $extracted["gslbservices"] "add gslb service"
|
|
|
+
|
|
|
+# ── Authentication vServers (AAA) ─────────────────────────────────────────────
|
|
|
+Emit-Objects "Authentication Virtual Servers" "authenticationvserver" $extracted["authvservers"] "add authentication vServer"
|
|
|
+
|
|
|
+# ── vServers ──────────────────────────────────────────────────────────────────
|
|
|
+Emit-Objects "Load Balancing Virtual Servers" "lbvserver" $extracted["lbvservers"] "add lb vServer"
|
|
|
+Emit-Objects "Content Switching Virtual Servers" "csvserver" $extracted["csvservers"] "add cs vServer"
|
|
|
+Emit-Objects "Citrix Gateway Virtual Servers" "vpnvserver" $extracted["vpnvservers"] "add vpn vServer"
|
|
|
+Emit-Objects "GSLB Virtual Servers" "gslbvserver" $extracted["gslbvservers"] "add gslb vServer"
|
|
|
+
|
|
|
+# ── vServer bindings (SSL / Policies) ────────────────────────────────────────
|
|
|
+Out-Section "SSL Virtual Server Bindings"
|
|
|
+
|
|
|
+function Emit-SSLvServerBindings ([string]$VSType, [System.Collections.Generic.List[string]]$VSNames) {
|
|
|
+ foreach ($vsName in ($VSNames | Select-Object -Unique)) {
|
|
|
+ Out-Line "# --- SSL bindings for $VSType $vsName ---"
|
|
|
+ # Cert bindings
|
|
|
+ $cBinds = Get-BindingsFor "${VSType}_sslcertkey_binding" $vsName
|
|
|
+ foreach ($b in $cBinds) {
|
|
|
+ if ($b.PSObject.Properties["certkeyname"] -and $b.certkeyname) {
|
|
|
+ $isCaCert = if ($b.PSObject.Properties["ca"] -and $b.ca) { " -CA" } else { "" }
|
|
|
+ Out-Line "bind ssl $VSType $vsName -certkeyName $($b.certkeyname)$isCaCert"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # Cipher bindings
|
|
|
+ $cipBinds = Get-BindingsFor "${VSType}_sslciphersuite_binding" $vsName
|
|
|
+ if ($cipBinds.Count -gt 0) {
|
|
|
+ Out-Line "unbind ssl $VSType $vsName -cipherName DEFAULT"
|
|
|
+ foreach ($b in $cipBinds) {
|
|
|
+ if ($b.PSObject.Properties["ciphername"] -and $b.ciphername) {
|
|
|
+ Out-Line "bind ssl $VSType $vsName -cipherName $($b.ciphername)"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ # SSL profile
|
|
|
+ $sslCfg = Invoke-Nitro -Method GET -Resource "sslvserver/$([uri]::EscapeDataString($vsName))"
|
|
|
+ if ($sslCfg -and $sslCfg.PSObject.Properties["sslvserver"]) {
|
|
|
+ $s = $sslCfg.sslvserver | Select-Object -First 1
|
|
|
+ if ($s -and $s.PSObject.Properties["sslprofile"] -and $s.sslprofile) {
|
|
|
+ Out-Line "set ssl $VSType $vsName -sslProfile $($s.sslprofile)"
|
|
|
+ }
|
|
|
+ }
|
|
|
+ Out-Line ""
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+Emit-SSLvServerBindings "vserver" $extracted["lbvservers"]
|
|
|
+Emit-SSLvServerBindings "vserver" $extracted["csvservers"]
|
|
|
+Emit-SSLvServerBindings "vserver" $extracted["vpnvservers"]
|
|
|
+Emit-SSLvServerBindings "vserver" $extracted["authvservers"]
|
|
|
+
|
|
|
+# ── Summary ───────────────────────────────────────────────────────────────────
|
|
|
+Out-Section "Extraction Summary"
|
|
|
+Out-Line "# LB vServers : $($extracted['lbvservers'].Count)"
|
|
|
+Out-Line "# CS vServers : $($extracted['csvservers'].Count)"
|
|
|
+Out-Line "# VPN vServers : $($extracted['vpnvservers'].Count)"
|
|
|
+Out-Line "# Auth vServers : $($extracted['authvservers'].Count)"
|
|
|
+Out-Line "# GSLB vServers : $($extracted['gslbvservers'].Count)"
|
|
|
+Out-Line "# Services : $($extracted['services'].Count)"
|
|
|
+Out-Line "# Service Groups : $($extracted['servicegroups'].Count)"
|
|
|
+Out-Line "# Servers : $($extracted['servers'].Count)"
|
|
|
+Out-Line "# Monitors : $($extracted['monitors'].Count)"
|
|
|
+Out-Line "# SSL Certs : $($extracted['sslcerts'].Count)"
|
|
|
+Out-Line "# SSL Profiles : $($extracted['sslprofiles'].Count)"
|
|
|
+Out-Line "# Rewrite Policies : $($extracted['rewritepolicies'].Count)"
|
|
|
+Out-Line "# Responder Policies : $($extracted['responderpolicies'].Count)"
|
|
|
+Out-Line "# AppFW Policies : $($extracted['appfwpolicies'].Count)"
|
|
|
+Out-Line "# Auth Policies (Adv) : $($extracted['authpolicies'].Count)"
|
|
|
+Out-Line "# LDAP Actions : $($extracted['ldapactions'].Count)"
|
|
|
+Out-Line "# RADIUS Actions : $($extracted['radiusactions'].Count)"
|
|
|
+Out-Line "# VPN Session Policies : $($extracted['vpnsessionpolicies'].Count)"
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Write output
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+if ($outputFile -and $outputFile -ne "screen") {
|
|
|
+ Write-Output-File $outputFile
|
|
|
+ # Try to open in a text editor - resolve full path automatically
|
|
|
+ $editorPath = $null
|
|
|
+
|
|
|
+ # 1. Check if the param value is already a valid full path or on PATH
|
|
|
+ if ($textEditor) {
|
|
|
+ if (Test-Path $textEditor -PathType Leaf) {
|
|
|
+ $editorPath = $textEditor
|
|
|
+ } elseif (Get-Command $textEditor -ErrorAction SilentlyContinue) {
|
|
|
+ $editorPath = $textEditor
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # 2. Auto-detect Notepad++ in common install locations
|
|
|
+ if (-not $editorPath) {
|
|
|
+ $nppPaths = @(
|
|
|
+ "$env:ProgramFiles\Notepad++\notepad++.exe",
|
|
|
+ "${env:ProgramFiles(x86)}\Notepad++\notepad++.exe",
|
|
|
+ "$env:LOCALAPPDATA\Programs\Notepad++\notepad++.exe"
|
|
|
+ )
|
|
|
+ foreach ($p in $nppPaths) {
|
|
|
+ if (Test-Path $p -PathType Leaf) { $editorPath = $p; break }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # 3. Try VS Code
|
|
|
+ if (-not $editorPath) {
|
|
|
+ foreach ($code in @("code","code.cmd")) {
|
|
|
+ if (Get-Command $code -ErrorAction SilentlyContinue) { $editorPath = $code; break }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ # 4. Fall back to built-in Notepad (always present on Windows)
|
|
|
+ if (-not $editorPath -and -not $IsMacOS) {
|
|
|
+ $editorPath = "notepad.exe"
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($editorPath) {
|
|
|
+ Write-Host "Opening output file with: $editorPath" -ForegroundColor Cyan
|
|
|
+ Start-Process -FilePath $editorPath -ArgumentList "`"$outputFile`""
|
|
|
+ } else {
|
|
|
+ Write-Host "No text editor found. Output saved to: $outputFile" -ForegroundColor Yellow
|
|
|
+ }
|
|
|
+} else {
|
|
|
+ $script:outputLines | ForEach-Object { Write-Output $_ }
|
|
|
+}
|
|
|
+
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+# Logout
|
|
|
+# ─────────────────────────────────────────────────────────────────────────────
|
|
|
+$logoutBody = @{ logout = @{} }
|
|
|
+try {
|
|
|
+ Invoke-Nitro -Method POST -Resource "logout" -Body $logoutBody | Out-Null
|
|
|
+ Write-Host "✔ Logged out of NetScaler." -ForegroundColor Green
|
|
|
+} catch {
|
|
|
+ # non-fatal
|
|
|
+}
|
|
|
+
|
|
|
+Write-Host "`nDone." -ForegroundColor Cyan
|