Init commit
This commit is contained in:
+107
@@ -0,0 +1,107 @@
|
||||
# Small helper for driving the agent: enqueues one command and waits for the ACK.
|
||||
#
|
||||
# powershell -File agent-cli.ps1 -Command "STATUS"
|
||||
# powershell -File agent-cli.ps1 -Status
|
||||
# powershell -File agent-cli.ps1 -Command "PS Get-Process | Select -First 3"
|
||||
#
|
||||
# Uses the same HMAC scheme the agent does, so it works against the mock worker
|
||||
# and the real Cloudflare Worker alike.
|
||||
|
||||
param(
|
||||
[string]$Worker = "http://127.0.0.1:8788",
|
||||
[string]$Agent = "testagent",
|
||||
[string]$Secret = "testsecret",
|
||||
[string]$Command = "",
|
||||
[switch]$Status,
|
||||
[int]$TimeoutSec = 30
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
function Get-Sha256Hex([byte[]]$Bytes)
|
||||
{
|
||||
$sha = [System.Security.Cryptography.SHA256]::Create()
|
||||
try
|
||||
{
|
||||
if ($null -eq $Bytes -or $Bytes.Length -eq 0) { $stream = New-Object System.IO.MemoryStream }
|
||||
else { $stream = New-Object System.IO.MemoryStream(, $Bytes) }
|
||||
return ([BitConverter]::ToString($sha.ComputeHash($stream)) -replace "-", "").ToLower()
|
||||
}
|
||||
finally { $sha.Dispose() }
|
||||
}
|
||||
|
||||
function Get-HmacHex([string]$Key, [string]$Message)
|
||||
{
|
||||
$hmac = New-Object System.Security.Cryptography.HMACSHA256
|
||||
try
|
||||
{
|
||||
$hmac.Key = [System.Text.Encoding]::UTF8.GetBytes($Key)
|
||||
return ([BitConverter]::ToString($hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Message))) -replace "-", "").ToLower()
|
||||
}
|
||||
finally { $hmac.Dispose() }
|
||||
}
|
||||
|
||||
function Invoke-Worker([string]$Path, [string]$Method = "GET", [byte[]]$Body)
|
||||
{
|
||||
if ($null -eq $Body) { $Body = [byte[]]@() }
|
||||
|
||||
$ts = [string][DateTimeOffset]::UtcNow.ToUnixTimeSeconds()
|
||||
$canonical = "$Agent`n$ts`n$Method`n$($Path.TrimStart('/'))`n$(Get-Sha256Hex $Body)"
|
||||
$headers = @{
|
||||
"X-Agent-Id" = $Agent
|
||||
"X-Agent-Ts" = $ts
|
||||
"X-Agent-Sign" = (Get-HmacHex $Secret $canonical)
|
||||
}
|
||||
|
||||
if ($Method -eq "POST")
|
||||
{
|
||||
return Invoke-WebRequest -Method Post -Uri "$Worker$Path" -Body ([byte[]]$Body) `
|
||||
-ContentType "application/octet-stream" -Headers $headers -UseBasicParsing
|
||||
}
|
||||
|
||||
return Invoke-WebRequest -Uri "$Worker$Path" -Headers $headers -UseBasicParsing
|
||||
}
|
||||
|
||||
function Decode-Last([string]$Value)
|
||||
{
|
||||
if (-not $Value) { return "" }
|
||||
|
||||
try { return [System.Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($Value)) }
|
||||
catch { return $Value }
|
||||
}
|
||||
|
||||
if ($Status)
|
||||
{
|
||||
$s = (Invoke-Worker -Path "/status").Content | ConvertFrom-Json
|
||||
"agent=$($s.agent) queued=$($s.queued) pending=$([bool]$s.pending)"
|
||||
if ($s.last) { Decode-Last $s.last }
|
||||
exit 0
|
||||
}
|
||||
|
||||
if (-not $Command)
|
||||
{
|
||||
throw "Usage: agent-cli.ps1 -Command '<command>' | -Status"
|
||||
}
|
||||
|
||||
$before = (Invoke-Worker -Path "/status").Content | ConvertFrom-Json
|
||||
$initialLast = $before.last
|
||||
|
||||
$null = Invoke-Worker -Path "/enqueue" -Method POST -Body ([System.Text.Encoding]::UTF8.GetBytes($Command))
|
||||
|
||||
$deadline = (Get-Date).AddSeconds($TimeoutSec)
|
||||
$seenPending = $false
|
||||
|
||||
while ((Get-Date) -lt $deadline)
|
||||
{
|
||||
Start-Sleep -Milliseconds 400
|
||||
|
||||
$s = (Invoke-Worker -Path "/status").Content | ConvertFrom-Json
|
||||
|
||||
if ($s.pending) { $seenPending = $true; continue }
|
||||
|
||||
if ($s.last -and $s.last -ne $initialLast) { Decode-Last $s.last; exit 0 }
|
||||
if ($seenPending -and $s.last) { Decode-Last $s.last; exit 0 }
|
||||
}
|
||||
|
||||
Write-Host "<timeout: agent may still be backing off>"
|
||||
exit 1
|
||||
Reference in New Issue
Block a user