param( [Parameter(Mandatory = $true)] [string]$Worker, [Parameter(Mandatory = $true)] [string]$Agent, [Parameter(Mandatory = $true)] [string]$Secret, [Parameter(Mandatory = $true)] [string]$Command ) # Signs requests exactly like the agent does: # hex(HMAC-SHA256(secret, agent \n ts \n METHOD \n path+query \n sha256hex(body))) # No secret is ever placed in a URL. $ErrorActionPreference = "Stop" $base = $Worker.TrimEnd('/') $bodyBytes = [System.Text.Encoding]::UTF8.GetBytes($Command) function Get-Sha256Hex([byte[]]$Bytes) { $sha = [System.Security.Cryptography.SHA256]::Create() try { $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) $hash = $hmac.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($Message)) return ([BitConverter]::ToString($hash) -replace "-", "").ToLower() } finally { $hmac.Dispose() } } $ts = [string][DateTimeOffset]::UtcNow.ToUnixTimeSeconds() $canonical = "$Agent`n$ts`nPOST`nenqueue`n$(Get-Sha256Hex $bodyBytes)" $sign = Get-HmacHex $Secret $canonical $headers = @{ "X-Agent-Id" = $Agent "X-Agent-Ts" = $ts "X-Agent-Sign" = $sign } $response = Invoke-WebRequest ` -Method Post ` -Uri "$base/enqueue" ` -Body $bodyBytes ` -ContentType "application/octet-stream" ` -Headers $headers ` -UseBasicParsing $response.Content