• 0

Powershell Download a Collector


Go to solution Solved by Mike Moniz,

Question

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

Link to post
Share on other sites

3 answers to this question

Recommended Posts

  • 1
  • Solution

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

 

  • Upvote 1
Link to post
Share on other sites
  • 0

So PowerShell is converting it to a String causing encoding problems. If you switch to Invoke-WebRequest the Content property will be a proper Byte array which you can save to file. See https://www.reddit.com/r/PowerShell/comments/719oip/downloading_a_file_via_http_directly_to_a_variable/dn9snst/ . Note that the pipeline version was extremely slow on my system but this version was quick.

$Response = Invoke-WebRequest -Uri $url -Method $Verb -Header $headers -ContentType "application/binary" -Verbose
$File = [System.IO.FileStream]::new('lm-filestream.exe', [System.IO.FileMode]::Create)
$File.write($Response.Content, 0, $Response.Content.Length)
$File.close()

 

 

 

 

Edited by Mike Moniz
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Answer this question...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.