Created
November 9, 2017 20:35
-
-
Save dedenker/52757bf8ac13548853a383f57499e2d1 to your computer and use it in GitHub Desktop.
This Powershell script is to listen on a port and react as ping function would do. Across domain allowed in headers!
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Function Start-Pong { | |
<# | |
.Synopsis | |
Creates a new HTTP Listener with PING reply function | |
.Description | |
This module is heavily based on a module that is a HTTP listener (see blog). | |
I just adjusted a little so the HASH convertion is missing and authentication can be ignored. | |
The function I only required is to "pong" a ping, given to a adres + port + namespace. | |
This function requires running from an elevated administrator prompt to open a port. | |
Use Ctrl-C to stop the listener. You'll need to send another web request to allow the listener to stop since | |
it will be blocked waiting for a request. | |
Pre-Fork Author: https://social.technet.microsoft.com/profile/powershell%20team/ | |
Based on: https://gallery.technet.microsoft.com/Simple-REST-api-for-b04489f1 | |
Mentioned blog: https://blogs.msdn.microsoft.com/powershell/2014/09/29/simple-http-api-for-executing-powershell-scripts/ | |
.Parameter Port | |
Port to listen, default is 8888 | |
.Parameter URL | |
URL to listen, default is / | |
.Parameter Auth | |
Optional! | |
Authentication Schemes to use, default is IntegratedWindowsAuthentication | |
.Example | |
Start-Pong -port 8080 -url ping | |
Will listen on port 8080 to recieve "ping" and will reply "pong" | |
This is to measure a PING value. | |
Start-Pong -port 8080 -url ping -Auth | |
Will do the same, but plus authentication | |
#> | |
Param ( | |
[Parameter()] | |
[Int] $Port = 8888, | |
[Parameter()] | |
[String] $Url = "", | |
[Parameter()] | |
[Boolean] $Auth = $False | |
) | |
Process { | |
$json = @" | |
{ | |
"ping": "pong" | |
} | |
"@ | |
$ErrorActionPreference = "Stop" | |
if ($Auth) {$Auth = [System.Net.AuthenticationSchemes]$Auth = [System.Net.AuthenticationSchemes]::IntegratedWindowsAuthentication} | |
$CurrentPrincipal = New-Object Security.Principal.WindowsPrincipal( [Security.Principal.WindowsIdentity]::GetCurrent()) | |
if ( -not ($currentPrincipal.IsInRole( [Security.Principal.WindowsBuiltInRole]::Administrator ))) { | |
Write-Error "This script must be executed from an elevated PowerShell session" -ErrorAction Stop | |
} | |
if ($Url.Length -gt 0 -and -not $Url.EndsWith('/')) { | |
$Url += "/" | |
} | |
$listener = New-Object System.Net.HttpListener | |
$prefix = "http://*:$Port/$Url" | |
$listener.Prefixes.Add($prefix) | |
if ($Auth) {$listener.AuthenticationSchemes = $Auth } | |
try { | |
$listener.Start() | |
while ($true) { | |
$statusCode = 200 | |
Write-Warning "Note that thread is blocked waiting for a request. After using Ctrl-C to stop listening, you need to send a valid HTTP request to stop the listener cleanly." | |
Write-Warning "Sending 'exit' command will cause listener to stop immediately" | |
Write-Verbose "Listening on $port..." | |
$context = $listener.GetContext() | |
$request = $context.Request | |
if (!$request.IsAuthenticated) { | |
if ($Url -eq "ping/") { | |
Write-Warning "zijn er" | |
$commandOutput = $json #"PONG" | |
$Format = "TEXT" | |
} else { | |
Write-Warning "Rejected request as user was not authenticated" | |
$statusCode = 403 | |
$commandOutput = "Unauthorized" | |
} | |
} else { | |
$identity = $context.User.Identity | |
Write-Verbose "Received request $(get-date) from $($identity.Name):" | |
$request | fl * | Out-String | Write-Verbose | |
# only allow requests that are the same identity as the one who started the listener | |
if ($identity.Name -ne $CurrentPrincipal.Identity.Name) { | |
Write-Warning "Rejected request as user doesn't match current security principal of listener" | |
$statusCode = 403 | |
$commandOutput = "Unauthorized" | |
} else { | |
if (-not $request.QueryString.HasKeys()) { | |
$commandOutput = "SYNTAX: command=<string> format=[JSON|TEXT|XML|NONE|CLIXML]" | |
$Format = "TEXT" | |
} else { | |
$command = $request.QueryString.Item("command") | |
if ($command -eq "exit") { | |
Write-Verbose "Received command to exit listener" | |
return | |
} | |
$Format = $request.QueryString.Item("format") | |
if ($Format -eq $Null) { | |
$Format = "JSON" | |
} | |
Write-Verbose "Command = $command" | |
Write-Verbose "Format = $Format" | |
try { | |
$script = $ExecutionContext.InvokeCommand.NewScriptBlock($command) | |
$commandOutput = & $script | |
} catch { | |
$commandOutput = $_ | ConvertTo-HashTable | |
$statusCode = 500 | |
} | |
} | |
$commandOutput = switch ($Format) { | |
TEXT { $commandOutput | Out-String ; break } | |
JSON { $commandOutput | ConvertTo-JSON; break } | |
XML { $commandOutput | ConvertTo-XML -As String; break } | |
CLIXML { [System.Management.Automation.PSSerializer]::Serialize($commandOutput) ; break } | |
default { "Invalid output format selected, valid choices are TEXT, JSON, XML, and CLIXML"; $statusCode = 501; break } | |
} | |
} | |
} | |
Write-Verbose "Response:" | |
if (!$commandOutput) { | |
$commandOutput = [string]::Empty | |
} | |
Write-Verbose $commandOutput | |
$response = $context.Response | |
$response.Headers.Add("Access-Control-Allow-Origin","*") | |
$response.StatusCode = $statusCode | |
$buffer = [System.Text.Encoding]::UTF8.GetBytes($commandOutput) | |
$response.ContentLength64 = $buffer.Length | |
$output = $response.OutputStream | |
$output.Write($buffer,0,$buffer.Length) | |
$output.Close() | |
} | |
} finally { | |
$listener.Stop() | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment