PSWinBGP.psm1
|
[Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSAvoidAssignmentToAutomaticVariable', 'IsWindows', Justification = 'IsWindows doesnt exist in PS5.1' )] [Diagnostics.CodeAnalysis.SuppressMessageAttribute( 'PSUseDeclaredVarsMoreThanAssignments', 'IsWindows', Justification = 'IsWindows doesnt exist in PS5.1' )] [CmdletBinding()] param() $baseName = [System.IO.Path]::GetFileNameWithoutExtension($PSCommandPath) $script:PSModuleInfo = Import-PowerShellDataFile -Path "$PSScriptRoot\$baseName.psd1" $script:PSModuleInfo | Format-List | Out-String -Stream | ForEach-Object { Write-Debug $_ } $scriptName = $script:PSModuleInfo.Name Write-Debug "[$scriptName] - Importing module" if ($PSEdition -eq 'Desktop') { $IsWindows = $true } #region [init] Write-Debug "[$scriptName] - [init] - Processing folder" #region [init] - [Initialize-PSWinBGP] Write-Debug "[$scriptName] - [init] - [Initialize-PSWinBGP] - Importing" # Initializing PSWinBGP (Command completer is used by some public functions) Register-ArgumentCompleter ` -CommandName Get-WinBGPRoute, Start-WinBGPRoute, Stop-WinBGPRoute, Start-WinBGPRouteMaintenance, Stop-WinBGPRouteMaintenance ` -ParameterName Name -ScriptBlock { param($commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters) # Define paramaters to $null to avoid syntax errors $null = $commandName, $parameterName, $wordToComplete, $commandAst, $fakeBoundParameters # Dynamically generate routes array if ($FakeBoundParameters.ComputerName) { [Array] $routes = (Get-WinBGPRoute -ComputerName $FakeBoundParameters.ComputerName) } else { [Array] $routes = (Get-WinBGPRoute) } # Return routes as arguments (IntelliSense) $routes | ForEach-Object { New-Object -Type System.Management.Automation.CompletionResult -ArgumentList ` $_.Name, ` "$(if ($_.ComputerName){"ComputerName: '$($_.ComputerName)' - RouteName: '$($_.Name)'"}else{$_.Name})", ` "ParameterValue", ` "$(if ($_.ComputerName){"ComputerName: '$($_.ComputerName)' - "})Network: '$($_.Network)' - Status: '$($_.Status)'" } } Write-Debug "[$scriptName] - [init] - [Initialize-PSWinBGP] - Done" #endregion [init] - [Initialize-PSWinBGP] Write-Debug "[$scriptName] - [init] - Done" #endregion [init] #region [functions] - [private] Write-Debug "[$scriptName] - [functions] - [private] - Processing folder" #region [functions] - [private] - [Invoke-PSWinBGP] Write-Debug "[$scriptName] - [functions] - [private] - [Invoke-PSWinBGP] - Importing" function Invoke-PSWinBGP() { <# .SYNOPSIS Inkoke WinBGP .DESCRIPTION Inkoke WinBGP using CLI for local call or API .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .EXAMPLE Invoke-PSWinBGP -ComputerName machine1,machine2 -Call routes # Get WinBGP status (Display WinBGP routes status) #> [CmdletBinding()] param( [Parameter(Mandatory = $true)] [String[]]$ComputerName, [Parameter(ParameterSetName = 'call', Mandatory = $true)] [String]$Call, # Call to perform [Parameter(Mandatory = $false)] [String]$RouteName # Select route to control ) if ($ComputerName -eq 'local') { switch ($call) { 'routes' { Invoke-Command { WinBGP } } 'startroute' { Invoke-Command { WinBGP -RouteName $RouteName -StartRoute } } 'stoproute' { Invoke-Command { WinBGP -RouteName $RouteName -StopRoute } } 'startmaintenance' { Invoke-Command { WinBGP -RouteName $RouteName -StartMaintenance } } 'stopmaintenance' { Invoke-Command { WinBGP -RouteName $RouteName -StopMaintenance } } } } else { if ($ComputerName -eq 'localhost') { [String]$AuthenticationMethod = $Script:PSWinBGP.LocalhostApiAuthenticationMethod [Int]$Port = $Script:PSWinBGP.LocalhostApiPort [String]$Protocol = $Script:PSWinBGP.LocalhostApiProtocol [Int]$Timeout = $Script:PSWinBGP.LocalhostApiTimeout } else { [String]$AuthenticationMethod = $Script:PSWinBGP.ApiAuthenticationMethod [Int]$Port = $Script:PSWinBGP.ApiPort [String]$Protocol = $Script:PSWinBGP.ApiProtocol [Int]$Timeout = $Script:PSWinBGP.ApiTimeout } # Initialize output variable $Output = @() $ErrorOutput = @() # Initialize error variable $ErrorCount = 0 foreach ($Computer in $ComputerName) { # Initialize output variable $ApiOutput = [PSCustomObject]@{} $ErrorOut = [PSCustomObject]@{} $ApiDefaultRequestURL = "$($Protocol)://$($Computer):$($Port)/api" $params = @{} $params.add('UseBasicParsing', $true) $params.add('TimeoutSec', $Timeout) $params.add('ContentType', 'application/json') # Only authentication method managed currently is 'Negotiate' (To be improved) if (($AuthenticationMethod -eq 'IntegratedWindowsAuthentication') -or ($AuthenticationMethod -eq 'Negotiate')) { $params.add('UseDefaultCredentials', $true) } # Get if ($call -eq 'routes') { $ApiRequestURL = "$ApiDefaultRequestURL/routes" } # Post if (($call -eq 'startmaintenance') -or ($call -eq 'stopmaintenance') -or ($call -eq 'startroute') -or ($call -eq 'stoproute')) { $ApiRequestMethod = 'Post' if ($call -eq 'startmaintenance') { $ApiRequestURL = "$ApiDefaultRequestURL/startmaintenance?routename=$RouteName" } if ($call -eq 'stopmaintenance') { $ApiRequestURL = "$ApiDefaultRequestURL/stopmaintenance?routename=$RouteName" } if ($call -eq 'startroute') { $ApiRequestURL = "$ApiDefaultRequestURL/startroute?routename=$RouteName" } if ($call -eq 'stoproute') { $ApiRequestURL = "$ApiDefaultRequestURL/stoproute?routename=$RouteName" } } # Test if target is reachable if ($PSVersionTable.PSVersion.Major -ge 7) { $ConnectivityTest = (Test-Connection -TcpPort $Port -TimeoutSeconds $Timeout -TargetName $Computer -Quiet) $params.add('SkipHttpErrorCheck', $true) $params.add('StatusCodeVariable', 'StatusCode') } else { if ($ComputerName -eq 'localhost') { # Bypass connectivity test when localhost (For speed performance) $ConnectivityTest = $true } else { $ConnectivityTest = (Test-NetConnection -ComputerName $computer -Port $port).TcpTestSucceeded } } if ($ConnectivityTest) { $params.add('uri', $ApiRequestURL) if ($ApiRequestMethod) { $params.add('Method', $ApiRequestMethod) } # Perform Rest API Call if ($PSVersionTable.PSVersion.Major -ge 7) { $RestApiCall = Invoke-RestMethod @params } else { # Try/catch because PS5 don't support status code and skip http error check try { $RestApiCall = Invoke-RestMethod @params } catch { $ErrorOut | Add-member -MemberType NoteProperty -Name 'Result' -Value "API call error: $($_)" $ErrorCount++ } } if ($RestApiCall) { $ApiOutput = $RestApiCall $ErrorOut | Add-member -MemberType NoteProperty -Name 'Result' -Value 'API connection OK' } else { if ($StatusCode) { $Value = "API return code: $([System.Net.HttpStatusCode]$StatusCode) ($StatusCode)" $ErrorOut | Add-Member -MemberType NoteProperty -Name 'Result' -Value $Value $ErrorCount++ } else { if ($PSVersionTable.PSVersion.Major -ge 7) { $ErrorOut | Add-member -MemberType NoteProperty -Name 'Result' -Value 'API call timeout' $ErrorCount++ } } } } else { $ErrorOut | Add-member -MemberType NoteProperty -Name 'Result' -Value 'API connection timeout' $ErrorCount++ } # Add ComputerName variable to output (except for localhost) if ($Computer -ne 'localhost') { $ApiOutput | Add-member -MemberType NoteProperty -Name 'ComputerName' -Value "$Computer" } $Output += $ApiOutput # Add ComputerName variable to output (except for localhost) if ($Computer -ne 'localhost') { $ErrorOut | Add-member -MemberType NoteProperty -Name 'ComputerName' -Value "$Computer" } $ErrorOutput += $ErrorOut } # If there is connection error, just return connection table if ($ErrorCount -eq 0) { # Return result return [PSCustomObject]$Output } else { return [PSCustomObject]$ErrorOutput } } } Write-Debug "[$scriptName] - [functions] - [private] - [Invoke-PSWinBGP] - Done" #endregion [functions] - [private] - [Invoke-PSWinBGP] Write-Debug "[$scriptName] - [functions] - [private] - Done" #endregion [functions] - [private] #region [functions] - [public] Write-Debug "[$scriptName] - [functions] - [public] - Processing folder" #region [functions] - [public] - [Get-WinBGPRoute] Write-Debug "[$scriptName] - [functions] - [public] - [Get-WinBGPRoute] - Importing" function Get-WinBGPRoute() { <# .SYNOPSIS WinBGP Remote Management - Get WinBGP Route .DESCRIPTION This function retrieve WinBGP Routes .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .PARAMETER Name Single or multiple Route Name (IntelliSense availalble) .EXAMPLE Get-WinBGPRoute -ComputerName machine1,machine2 #> [CmdletBinding()] param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [String[]]$ComputerName = 'local', [Parameter(Mandatory = $false)] [Alias('RouteName')] [String[]]$Name ) process { $Routes = Invoke-PSWinBGP -ComputerName $ComputerName -Call 'routes' # Filter if Name is provided if ($Name) { $Routes | Where-Object { $_.Name -in $Name } } else { $Routes } } } Write-Debug "[$scriptName] - [functions] - [public] - [Get-WinBGPRoute] - Done" #endregion [functions] - [public] - [Get-WinBGPRoute] #region [functions] - [public] - [Set-PSWinBGPConfig] Write-Debug "[$scriptName] - [functions] - [public] - [Set-PSWinBGPConfig] - Importing" function Set-PSWinBGPConfig { <# .SYNOPSIS Set PSWinBBGP module configuration. .DESCRIPTION Set PSWinBBGP module configuration, and $PSWinBBGP module variable. .PARAMETER ApiAuthenticationMethod API Authentication Method (Default: IntegratedWindowsAuthentication) .PARAMETER ApiPort API Port (Default: 8888) .PARAMETER ApiProtocol API Protocol (Default: HTTPS) .PARAMETER ApiTimeout API Timeout (Default: 10s) .PARAMETER LocalhostApiAuthenticationMethod Localhost API Authentication Method (Default: Anonymous) .PARAMETER LocalhostApiPort Localhost API Port (Default: 8888) .PARAMETER LocalhostApiProtocol Localhost API Protocol (Default: HTTP) .PARAMETER LocalhostApiTimeout Localhost API Timeout (Default: 5s) #> [CmdletBinding(SupportsShouldProcess = $true)] param( [string]$ApiAuthenticationMethod, [Int]$ApiPort, [string]$ApiProtocol, [Int]$ApiTimeout, [string]$LocalhostApiAuthenticationMethod, [Int]$LocalhostApiPort, [string]$LocalhostApiProtocol, [Int]$LocalhostApiTimeout ) if ($pscmdlet.ShouldProcess('$Script:PSWinBGP', 'Set config')) { switch ($PSBoundParameters.Keys) { 'ApiAuthenticationMethod' { $Script:PSWinBGP.ApiAuthenticationMethod = $ApiAuthenticationMethod } 'ApiPort' { $Script:PSWinBGP.ApiPort = $ApiPort } 'ApiProtocol' { $Script:PSWinBGP.ApiProtocol = $ApiProtocol } 'ApiTimeout' { $Script:PSWinBGP.ApiTimeout = $ApiTimeout } 'LocalhostApiAuthenticationMethod' { $Script:PSWinBGP.LocalhostApiAuthenticationMethod = $LocalhostApiAuthenticationMethod } 'LocalhostApiPort' { $Script:PSWinBGP.LocalhostApiPort = $LocalhostApiPort } 'LocalhostApiProtocol' { $Script:PSWinBGP.LocalhostApiProtocol = $LocalhostApiProtocol } 'LocalhostApiTimeout' { $Script:PSWinBGP.LocalhostApiTimeout = $LocalhostApiTimeout } } } } Write-Debug "[$scriptName] - [functions] - [public] - [Set-PSWinBGPConfig] - Done" #endregion [functions] - [public] - [Set-PSWinBGPConfig] #region [functions] - [public] - [Start-WinBGPRoute] Write-Debug "[$scriptName] - [functions] - [public] - [Start-WinBGPRoute] - Importing" function Start-WinBGPRoute() { <# .SYNOPSIS WinBGP Remote Management - Start Route .DESCRIPTION This function perform Start Route .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .PARAMETER Name Single or multiple Route Name (IntelliSense availalble) .EXAMPLE Start-WinBGPRoute -ComputerName machine1,machine2 -Name route1.contoso.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [String[]]$ComputerName = 'local', [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('RouteName')] [String[]]$Name ) process { # Parsing all routes provided foreach ($Route in $Name) { # If action is confirmed if ($PSCmdlet.ShouldProcess("$($Route)$(if ($ComputerName -ne 'local'){" [ComputerName: $($ComputerName)]"})", 'Start WinBGP route')) { Invoke-PSWinBGP -ComputerName $ComputerName -call 'startroute' -RouteName $Route } } } } Write-Debug "[$scriptName] - [functions] - [public] - [Start-WinBGPRoute] - Done" #endregion [functions] - [public] - [Start-WinBGPRoute] #region [functions] - [public] - [Start-WinBGPRouteMaintenance] Write-Debug "[$scriptName] - [functions] - [public] - [Start-WinBGPRouteMaintenance] - Importing" function Start-WinBGPRouteMaintenance() { <# .SYNOPSIS WinBGP Remote Management - Start Route Maintenance .DESCRIPTION This function perform Start Route Maintenance .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .PARAMETER Name Single or multiple Route Name (IntelliSense availalble) .EXAMPLE Start-WinBGPRouteMaintenance -ComputerName machine1,machine2 -Name route1.contoso.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [String[]]$ComputerName = 'local', [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('RouteName')] [String[]]$Name ) process { # Parsing all routes provided foreach ($Route in $Name) { # If action is confirmed if ( $PSCmdlet.ShouldProcess( "$($Route)$( if ($ComputerName -ne 'local') { " [ComputerName: $($ComputerName)]" } )", 'Start WinBGP route maintenance' ) ) { Invoke-PSWinBGP -ComputerName $ComputerName -call 'startmaintenance' -RouteName $Route } } } } Write-Debug "[$scriptName] - [functions] - [public] - [Start-WinBGPRouteMaintenance] - Done" #endregion [functions] - [public] - [Start-WinBGPRouteMaintenance] #region [functions] - [public] - [Stop-WinBGPRoute] Write-Debug "[$scriptName] - [functions] - [public] - [Stop-WinBGPRoute] - Importing" function Stop-WinBGPRoute() { <# .SYNOPSIS WinBGP Remote Management - Stop Route .DESCRIPTION This function perform Stop Route .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .PARAMETER Name Single or multiple Route Name (IntelliSense availalble) .EXAMPLE Stop-WinBGPRoute -ComputerName machine1,machine2 -Name route1.contoso.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'High')] param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [String[]]$ComputerName = 'local', [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('RouteName')] [String[]]$Name ) process { # Parsing all routes provided foreach ($Route in $Name) { # If action is confirmed if ($PSCmdlet.ShouldProcess("$($Route)$(if ($ComputerName -ne 'local'){" [ComputerName: $($ComputerName)]"})", 'Stop WinBGP route')) { Invoke-PSWinBGP -ComputerName $ComputerName -call 'stoproute' -RouteName $Route } } } } Write-Debug "[$scriptName] - [functions] - [public] - [Stop-WinBGPRoute] - Done" #endregion [functions] - [public] - [Stop-WinBGPRoute] #region [functions] - [public] - [Stop-WinBGPRouteMaintenance] Write-Debug "[$scriptName] - [functions] - [public] - [Stop-WinBGPRouteMaintenance] - Importing" function Stop-WinBGPRouteMaintenance() { <# .SYNOPSIS WinBGP Remote Management - Stop Route Maintenance .DESCRIPTION This function perform Stop Route Maintenance .PARAMETER ComputerName Single or multiple ComputerName (Default: localhost) .PARAMETER Name Single or multiple Route Name (IntelliSense availalble) .EXAMPLE Stop-WinBGPRouteMaintenance -ComputerName machine1,machine2 -Name route1.contoso.com #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = 'Medium')] param( [Parameter(Mandatory = $false, ValueFromPipelineByPropertyName = $true)] [String[]]$ComputerName = 'local', [Parameter(Mandatory = $true, ValueFromPipelineByPropertyName = $true)] [Alias('RouteName')] [String[]]$Name ) process { # Parsing all routes provided foreach ($Route in $Name) { # If action is confirmed if ( $PSCmdlet.ShouldProcess( "$($Route)$( if ($ComputerName -ne 'local') { " [ComputerName: $($ComputerName)]" } )", 'Stop WinBGP route maintenance' ) ) { Invoke-PSWinBGP -ComputerName $ComputerName -call 'stopmaintenance' -RouteName $Route } } } } Write-Debug "[$scriptName] - [functions] - [public] - [Stop-WinBGPRouteMaintenance] - Done" #endregion [functions] - [public] - [Stop-WinBGPRouteMaintenance] Write-Debug "[$scriptName] - [functions] - [public] - Done" #endregion [functions] - [public] #region [variables] - [private] Write-Debug "[$scriptName] - [variables] - [private] - Processing folder" #region [variables] - [private] - [PSWinBGP-default] Write-Debug "[$scriptName] - [variables] - [private] - [PSWinBGP-default] - Importing" $script:PSWinBGP = @{ LocalhostApiAuthenticationMethod = 'Anonymous' LocalhostApiPort = 8888 LocalhostApiProtocol = 'http' LocalhostApiTimeout = 5 ApiAuthenticationMethod = 'IntegratedWindowsAuthentication' ApiPort = 8888 ApiProtocol = 'https' ApiTimeout = 10 } Write-Debug "[$scriptName] - [variables] - [private] - [PSWinBGP-default] - Done" #endregion [variables] - [private] - [PSWinBGP-default] Write-Debug "[$scriptName] - [variables] - [private] - Done" #endregion [variables] - [private] #region Member exporter $exports = @{ Alias = '*' Cmdlet = '' Function = @( 'Get-WinBGPRoute' 'Set-PSWinBGPConfig' 'Start-WinBGPRoute' 'Start-WinBGPRouteMaintenance' 'Stop-WinBGPRoute' 'Stop-WinBGPRouteMaintenance' ) Variable = '' } Export-ModuleMember @exports #endregion Member exporter |