Powershell Download a Collector
I've been working on a Powershell method to download a collector. I'm to the point where I've got content, but no matter how I write the file ($content > "lm.exe", $content | Out-File "lm.exe" (tried all the encoding options), or $content | Set-Content lm.exe) the resulting file will not execute.
https://XXXX.logicmonitor.com/santaba/rest/setting/collectors/1005/installers/Win64?collectorSize=small
$i = Get-LMCollectorInstaller -Account "XXXX" -CollectorId 1005 -CollectorSize small -Platform Win64 -Verbose
VERBOSE: Verb:GET Epoch:1578077331506 Data: resourcePath:/setting/collectors/1005/installers/Win64
VERBOSE: Url: https://XXXX.logicmonitor.com/santaba/rest/setting/collectors/1005/installers/Win64?collectorSize=small, Method: GET, Header:
System.Collections.Generic.Dictionary`2[System.String,System.String]
VERBOSE: GET https://XXXX.logicmonitor.com/santaba/rest/setting/collectors/1005/installers/Win64?collectorSize=small with 0-byte payload
VERBOSE: received -1-byte response of content type application/binary
$i | Set-Content .\Desktop\lm.exe
$i > .\Desktop\lm.exe
Running both yields a "This app can't run on your PC" popup on Windows 10 and Windows Server 2016. The file sizes are _almost_ the same (291,802,970 [not working] vs. 291,802,968 [working]) which makes me think it's an encoding issue, but I also tried all the Out-File encoding options with the same results.
$httpVerb = "GET"
$resourcePath = "/setting/collectors/$CollectorId/installers/$Platform"
$Query = "?collectorSize=$CollectorSize"
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
<# request details #>
$httpVerb = $Verb
$resourcePath = $Path
<# Construct URL #>
$url = 'https://' + $Account + '.logicmonitor.com/santaba/rest' + $resourcePath + $Query
<# Get current time in milliseconds #>
$epoch = [Math]::Round((New-TimeSpan -start (Get-Date -Date "1/1/1970") -end (Get-Date).ToUniversalTime()).TotalMilliseconds)
<# Concatenate Request Details #>
Write-Verbose "Verb:$httpVerb Epoch:$epoch Data:$Data resourcePath:$resourcePath"
$requestVars = $httpVerb + $epoch + $Data + $resourcePath
<# Construct Signature #>
$hmac = New-Object System.Security.Cryptography.HMACSHA256
$hmac.Key = [Text.Encoding]::UTF8.GetBytes($AccessKey)
$signatureBytes = $hmac.ComputeHash([Text.Encoding]::UTF8.GetBytes($requestVars))
$signatureHex = [System.BitConverter]::ToString($signatureBytes) -replace '-'
$signature = [System.Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($signatureHex.ToLower()))
<# Construct Headers #>
$auth = 'LMv1 ' + $AccessId + ':' + $signature + ':' + $epoch
$headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]"
$headers.Add("Authorization",$auth)
$headers.Add("Content-Type",'application/json')
$response = Invoke-RestMethod -Uri $url -Method $Verb -Header $headers -ContentType "application/json"
Write-Output $response
It seems to work for me if I use the -OutFile parameter with Invoke-RestMethod but didn't figure out having it assigned to a variable that is then outputted. I also changed the content type to binary instead of json since you are not looking for json data, but seems LM will send binary data anyway.
Invoke-RestMethod -Uri $url -Method $Verb -Header $headers -ContentType "application/binary" -OutFile "lm-out.exe" -Verbose