Converting a cURL into PowerShell Invoke-RESTMethod

A couple of projects recently involved using REST APIs to manage storage and auditing solutions. The problem is both the companies product support pages did not list any examples using PowerShell so here are some notes on how to convert the examples they provide into PowerShell using

Invoke-RestMethod

During my discovery someone recommended Postman as a good tool to test REST APIs – it’s a nice simple interface and it will help you make sense of the URL you need to create in order to use with the -URL switch of Invoke-RESTMetthod and speed up testing so I’;d definitely recommend this to someone trying to figure out a REST API.

The product we were testing has an interactive API page which is actually pretty cool as you can plug in values and it will actually show you on screen in the web page all the returned values or an error code if it didn’t work.

For this example I’m going to convert this cURL to Powershell
https://developer.tenable.com/reference#assets-list-assets

curl –request GET \
–url https://cloud.tenable.com/assets \
–header ‘accept: application/json’
–header ‘x-apikeys: accessKey={ACCESS_KEY};secretKey={SECRET_KEY}’

we can see some obvious values to extract here and I created variables to hold the them using even more obvious names 🙂

$URL = ‘ https://cloud.tenable.com/assets’

and a header but if you look at the command help you can see that the header needs to be a hashtable


$headers = @{} # to create a hashtable
$headers.Add(‘accept’,’application/json’
$headers.Add(‘x-apikeys’,”accessKey=$accessKey;secretKey=$secretKey)
# these keys are generated int eh management portal

Now we are ready to call the REST-API like this

$response = Invoke-RestMethod -Uri $URL -ContentType ‘application/json’ `
-Headers $headers

You can now start to interogate the response variable to get what you need.

In this case $response.Access provided the information on each asset in the system – however there was a limit of 5000 objects returned. When this happens there is usually a way of controlling how many objects are returned and where to start, i.e.a limit and an offset. Once you find out how to do this you make multiple calls to the URL using a different offset value each time.

Nasuni does this by sending a parameter which is a string appended to the end of the URL like this:

https://$host.api/v1.1/volumes/folder-quotas/?limit=$limit&offset=$offset

we use a simple loop and increment the $offset variable each time in the loop.

For this system Teneble though this command did not have any controls to page through the data instead you need to request the system build a report and then you can download the report in chunks ( as they call them ).

This page tells you how :

https://developer.tenable.com/reference#exports

curl --request POST \   
--url https://cloud.tenable.com/assets/export \
--header 'accept: application/json' \
--header 'content-type: application/json' \
--header 'x-apikeys: accessKey={ACCESS_KEY};secretKey={SECRET_KEY}'

and this returns and export UUID : 'export_uuid'
$URL = "https://cloud.tenable.com/assets/export"
$exportUUID = Invoke-RestMethod -Uri $URL -ContentType 'application/json'
-Headers $headers

Next you monitor the progress of the export by calling this URL

curl --request GET \
--url https://cloud.tenable.com/assets/export/export_uuid/status \
--header 'accept: application/json' \
--header 'x-apikeys: accessKey={ACCESS_KEY};secretKey={SECRET_KEY}'

$URL = "https://cloud.tenable.com/assets/export/$exportUUID/status"
$Status = Invoke-RestMethod -Uri $URL -ContentType 'application/json'
-Headers $headers

This will return an object with these attributes
‘status’ and ‘chunks_available’ ‘ put the code in a while loop and wait for status to be ‘FINISHED’
While { <script block here> } ($status -ne ‘FINISHED’)

make sure you have a way of exiting this loop if it takes too long or something goes wrong

Now when the loop has completed you can iterate through the chunks using a for loop and download each chunk like this

curl --request GET \   
--url https://cloud.tenable.com/assets/export/export_uuid/chunks/chunk_id \ --header 'accept: application/json' \
--header 'x-apikeys: accessKey={ACCESS_KEY};secretKey={SECRET_KEY}'
for ($index = 1; $index -lt $($status.chunks_available.count); $index++) {
$URL = "https://cloud.tenable.com/assets/export/$exportUUID/chunks/$index"
$(Invoke-RestMethod -Uri $URL -ContentType 'application/json'
-Headers $headers) | export-csv c:\temp\myAssets.csv -append
}

Hopefully you get the idea – oh one last problem is most of the columns in this instance are arrays so these don’t export very well to a CSV file but if you google this function your problems will be solved just pipe it through this function first.

https://gallery.technet.microsoft.com/scriptcenter/Convert-OutoutForCSV-6e552fc6

I hope this helps speed up your REST API scripting …